Clear code, work on DMA timing and calibration

experimental
F5OEO 2016-09-02 09:59:25 +00:00
rodzic bbdcba4f1d
commit 25e5869d2e
6 zmienionych plików z 243 dodań i 343 usunięć

Wyświetl plik

@ -89,6 +89,7 @@ char InitDma(void *FunctionTerminate, int* skipSignals)
printf("Failed to open mailbox\n");
return(0);
}
printf("%d Size NUM PAGES %d PAGE_SIZE %d\n",(sizeof(struct control_data_s)),NUM_PAGES,PAGE_SIZE);
mbox.mem_ref = mem_alloc(mbox.handle, NUM_PAGES* PAGE_SIZE, PAGE_SIZE, mem_flag);
/* TODO: How do we know that succeeded? */
//printf("mem_ref %x\n", mbox.mem_ref);

Wyświetl plik

@ -24,7 +24,7 @@ uint32_t mem_phys_to_virt(volatile uint32_t phys);
#define NUM_CB_PWM_FREQUENCY 8
//#define MBFILE DEVICE_FILE_NAME /* From mailbox.h */
#define NUM_SAMPLES_MAX (4000)
#define CBS_SIZE_BY_SAMPLE (5)
#define CBS_SIZE_BY_SAMPLE (3)
#define NUM_CBS_MAIN ((NUM_SAMPLES_MAX * CBS_SIZE_BY_SAMPLE))
#define NUM_CBS (NUM_CBS_MAIN)
@ -38,6 +38,7 @@ uint32_t mem_phys_to_virt(volatile uint32_t phys);
#define BCM2708_DMA_PER_MAP(x) ((x)<<16)
#define BCM2708_DMA_END (1<<1)
#define BCM2708_DMA_RESET (1<<31)
#define BCM2708_DMA_ABORT (1<<30)
#define BCM2708_DMA_INT (1<<2)
#define DMA_CS (0x00/4)
@ -46,6 +47,14 @@ uint32_t mem_phys_to_virt(volatile uint32_t phys);
#define BUS_TO_PHYS(x) ((x)&~0xC0000000)
#define DMA_CS_RESET (1<<31)
#define DMA_CS_ABORT (1<<30)
#define DMA_CS_DISDEBUG (1<<28)
#define DMA_CS_END (1<<1)
#define DMA_CS_ACTIVE (1<<0)
#define DMA_CS_PRIORITY(x) ((x)&0xf << 16)
#define DMA_CS_PANIC_PRIORITY(x) ((x)&0xf << 20)
#define PAGE_SIZE 4096
#define PAGE_SHIFT 12
#define NUM_PAGES ((sizeof(struct control_data_s) + PAGE_SIZE - 1) >> PAGE_SHIFT)
@ -93,31 +102,25 @@ page_map_t *page_map;
uint8_t *virtbase;
#define PWM_STEP_MAXI 200
typedef struct {
//uint32_t Frequency1;
//uint32_t Frequency2;
uint32_t FrequencyTab[PWM_STEP_MAXI];
uint32_t Amplitude1;
uint32_t Amplitude2;
uint32_t PWMF1;
uint32_t PWMF2;
uint32_t WaitForThisSample;
uint32_t PCMRegister;
uint32_t FrequencyTab[200];
uint32_t debugSet;
uint32_t debugClear;
} sample_t;
struct control_data_s {
dma_cb_t cb[NUM_CBS];//+1 ??
dma_cb_t cbdma2[NUM_CB_PWM_FREQUENCY];
sample_t sample[NUM_SAMPLES_MAX];
uint32_t GpioDebugPWMF;
uint32_t GpioDebugSampleRate;
uint32_t SharedFrequency1;
uint32_t SharedFrequency2;
uint32_t DmaPwmfControlRegister;
uint32_t SharedFrequencyTab[100];
};
struct control_data_s *ctl;

Wyświetl plik

@ -20,14 +20,14 @@ char InitGpio()
{
BCM2708_PERI_BASE = info.peripheralBase ;
dram_phys_base = 0x40000000;
mem_flag = 0x0c;
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))
{
BCM2708_PERI_BASE = info.peripheralBase ;
dram_phys_base = 0xc0000000;
mem_flag = 0x04;
mem_flag = MEM_FLAG_L1_NONALLOCATING/*MEM_FLAG_DIRECT*/|MEM_FLAG_HINT_PERMALOCK|MEM_FLAG_NO_INIT;//0x04;
}
}

Wyświetl plik

@ -93,4 +93,15 @@ int gpioSetMode(unsigned gpio, unsigned mode);
#define GPFSEL0 (0x00/4)
#define GPFSEL1 (0x04/4)
#define GPFSEL2 (0x08/4)
// ---- Memory allocating defines
// https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
#define MEM_FLAG_DISCARDABLE (1 << 0) /* can be resized to 0 at any time. Use for cached data */
#define MEM_FLAG_NORMAL (0 << 2) /* normal allocating alias. Don't use from ARM */
#define MEM_FLAG_DIRECT (1 << 2) /* 0xC alias uncached */
#define MEM_FLAG_COHERENT (2 << 2) /* 0x8 alias. Non-allocating in L2 but coherent */
#define MEM_FLAG_L1_NONALLOCATING (MEM_FLAG_DIRECT | MEM_FLAG_COHERENT) /* Allocating in L2 */
#define MEM_FLAG_ZERO ( 1 << 4) /* initialise buffer to all zeros */
#define MEM_FLAG_NO_INIT ( 1 << 5) /* don't initialise (default is initialise to all ones */
#define MEM_FLAG_HINT_PERMALOCK (1 << 6) /* Likely to be locked for long periods of time. */
#endif

Wyświetl plik

@ -65,7 +65,6 @@ Optimize CPU on PWMFrequency
#define SCHED_PRIORITY 30 //Linux scheduler priority. Higher = more realtime
//#define WITH_MEMORY_BUFFER
#define PROGRAM_VERSION "0.2"
@ -84,6 +83,12 @@ Optimize CPU on PWMFrequency
#define HEADER_SIZE 44
// DMA TIMING : depends on Pi Model : Calibration is better
#define FREQ_DELAY_TIME 0
int FREQ_MINI_TIMING=157;
int PWMF_MARGIN = 1120; //A Margin for now at 1us with PCM ->OK
int globalppmpll=0;
typedef unsigned char uchar; // 8 bit
typedef unsigned short uint16; // 16 bit
typedef unsigned int uint; // 32 bits
@ -120,33 +125,25 @@ static void udelay(int us)
static void stop_dma(void)
{
#ifdef WITH_MEMORY_BUFFER
//pthread_cancel(th1);
EndOfApp=1;
pthread_join(th1, NULL);
#endif
if (FileInHandle != -1) {
close(FileInHandle);
FileInHandle = -1;
}
if (dma_reg) {
//Stop Main DMA
dma_reg[DMA_CS+DMA_CHANNEL*0x40] = BCM2708_DMA_INT | BCM2708_DMA_END;
//STop DMA
dma_reg[DMA_CS+DMA_CHANNEL*0x40] |= DMA_CS_ABORT;
udelay(100);
dma_reg[DMA_CS+DMA_CHANNEL*0x40] = BCM2708_DMA_RESET;
dma_reg[DMA_CS+DMA_CHANNEL*0x40]&= ~DMA_CS_ACTIVE;
dma_reg[DMA_CS+DMA_CHANNEL*0x40] |= DMA_CS_RESET;
udelay(100);
//Stop DMA PWMFrequency
/*
dma_reg[DMA_CS+DMA_CHANNEL_PWMFREQUENCY*0x40] = BCM2708_DMA_INT | BCM2708_DMA_END;
udelay(100);
dma_reg[DMA_CS+DMA_CHANNEL_PWMFREQUENCY*0x40] = BCM2708_DMA_RESET;
udelay(100);
*/
//printf("Reset DMA Done\n");
clk_reg[GPCLK_CNTL] = 0x5A << 24 | 0 << 9 | 1 << 4 | 6; //NO MASH !!!
udelay(500);
gpio_reg[GPFSEL0] = (gpio_reg[GPFSEL0] & ~(7 << 12)) | (0 << 12); //DISABLE CLOCK - In case used by digilite
gpio_reg[GPFSEL0] = (gpio_reg[GPFSEL0] & ~(7 << 12)) | (0 << 12); //DISABLE CLOCK -
clk_reg[PWMCLK_CNTL] = 0x5A000006 | (0 << 9) ;
udelay(500);
clk_reg[PCMCLK_CNTL] = 0x5A000006;
@ -201,7 +198,7 @@ void setSchedPriority(int priority)
}
uint32_t DelayFromSampleRate=0;
int Instrumentation=1;
int Instrumentation=0;
int UsePCMClk=0;
uint32_t Originfsel=0;
@ -224,18 +221,12 @@ int SetupGpioClock(uint32_t SymbolRate,double TuningFrequency)
if(UsePCMClk==1)
gpio_reg[GPFSEL0] = (Originfsel & ~(7 << 12)) | (4 << 12); //ENABLE CLOCK ON GPIO CLK
/*
gpio_reg[GPFSEL0] = (gpio_reg[GPFSEL0] & ~(7 << 12)) | (4 << 12); //ENABLE CLOCK ON GPIO CLK
usleep(1000);
clk_reg[GPCLK_CNTL] = 0x5A << 24 |0<<4 | PLL_1GHZ;
usleep(1000);
clk_reg[GPCLK_CNTL] = 0x5A << 24 | MASH << 9 | 1 << 4 | PLL_1GHZ; // MASH 1
*/
// ------------------- MAKE MAX OUTPUT CURRENT FOR GPIO -----------------------
char OutputPower=7;
pad_gpios_reg[PADS_GPIO_0] = 0x5a000000 + (OutputPower&0x7) + (1<<4) + (0<<3); // Set output power for I/Q GPIO18/GPIO19
#ifdef USE_PCM
//------------------- Init PCM ------------------
pcm_reg[PCM_CS_A] = 1; // Disable Rx+Tx, Enable PCM block
udelay(100);
@ -247,8 +238,7 @@ int SetupGpioClock(uint32_t SymbolRate,double TuningFrequency)
FreqDividerPCM=(int) ((double)PllFreq1GHZ/(SymbolRate*NbStepPCM/**PwmNumberStep*/));
FreqFractionnalPCM=4096.0 * (((double)PllFreq1GHZ/(SymbolRate*NbStepPCM/**PwmNumberStep*/))-FreqDividerPCM);
//FreqDividerPCM=(int) ((double)PllFreq1GHZ/(1000000L*NbStepPCM/**PwmNumberStep*/)); //SET TO 10MHZ = 100ns
//FreqFractionnalPCM=4096.0 * (((double)PllFreq1GHZ/(1000000L*NbStepPCM/**PwmNumberStep*/))-FreqDividerPCM);
printf("SampleRate=%d\n",SymbolRate);
if((FreqDividerPCM>4096)||(FreqDividerPCM<2)) printf("Warning : SampleRate is not valid\n");
clk_reg[PCMCLK_DIV] = 0x5A000000 | ((FreqDividerPCM)<<12) | FreqFractionnalPCM;
@ -256,17 +246,7 @@ int SetupGpioClock(uint32_t SymbolRate,double TuningFrequency)
//printf("Div PCM %d FracPCM %d\n",FreqDividerPCM,FreqFractionnalPCM);
DelayFromSampleRate=(1e9/(SymbolRate));
//printf("Delay PCM (min step)=%d\n",DelayFromSampleRate);
//uint32_t DelayFromSampleRate=(1000000.0-2080.0)/27.4425;
//uint32_t DelayFromSampleRate=1000000;
//uint32_t DelayFromSampleRate=round((1000000-(2300))/27.4425);
//TimeDelay=0 : 2.08us
//TimeDelay=10000 : 280us
//TimdeDelay=100000 :2774us
//TimdeDelay=1000000 : 27400 us
//uint32_t DelayFromSampleRate=5000;
//printf("DelaySample %d Delay %d\n",DelayFromSampleRate,(int)(27.4425*DelayFromSampleRate+2300));
pcm_reg[PCM_TXC_A] = 0<<31 | 1<<30 | 0<<20 | 0<<16; // 1 channel, 8 bits
udelay(100);
@ -282,10 +262,10 @@ int SetupGpioClock(uint32_t SymbolRate,double TuningFrequency)
clk_reg[PCMCLK_CNTL] = 0x5A000010 |(1 << 9)| PLL_1GHZ /*PLL_1GHZ*/; // Source=PLLC and enable
udelay(100);
pcm_reg[PCM_CS_A] |= 1<<2; //START TX PCM
#endif
// FIN PCM
//INIT PWM in Serial Mode
//INIT PWM in Serial Mode : WE USE PWM OUPUT
if(UsePCMClk==0)
{
gpioSetMode(18, 2); /* set to ALT5, PWM1 : RF On PIN */
@ -310,7 +290,7 @@ int SetupGpioClock(uint32_t SymbolRate,double TuningFrequency)
}
// FIN INIT PWM
//******************* INIT CLK MODE
//******************* INIT CLK MODE : WE OUTPUT CLK INSTEAD OF PWM OUTPUT
if(UsePCMClk==1)
{
clk_reg[GPCLK_CNTL] = 0x5A000000 | (MASH << 9) |PllNumber/*PLL_1GHZ*/ ;
@ -319,6 +299,8 @@ int SetupGpioClock(uint32_t SymbolRate,double TuningFrequency)
udelay(300);
clk_reg[GPCLK_CNTL] = 0x5A000010 | (MASH << 9) | PllNumber /*PLL_1GHZ*/; //MASH3 : A TESTER SI MIEUX en MASH1
}
ctl = (struct control_data_s *)virtbase; // Struct ctl is mapped to the memory allocated by RpiDMA (Mailbox)
dma_cb_t *cbp = ctl->cb;
@ -333,30 +315,16 @@ int SetupGpioClock(uint32_t SymbolRate,double TuningFrequency)
uint32_t phys_gpio_pads_addr =0x7e10002c;
uint32_t phys_pcm_clock = 0x7e10109c ;
uint32_t phys_pcm_clock_div_addr = 0x7e10109c;//CLOCK Frequency Setting
uint32_t phys_DmaPwmfRegCtrl = 0x7e007000+DMA_CHANNEL_PWMFREQUENCY*0x100+0x4;
uint32_t phys_gpfsel = 0x7E200000 ;
int samplecnt;
gpioSetMode(27,1); // OSCILO SUR PIN 27
ctl->GpioDebugSampleRate=1<<27; // GPIO 27/ PIN 13 HEADER IS DEBUG SIGNAL OF SAMPLERATE
ctl->DmaPwmfControlRegister=mem_virt_to_phys((void *)(ctl->cbdma2) );
for (samplecnt = 0; samplecnt < NUM_SAMPLES ; samplecnt++)
{
//ctl->sample[samplecnt].WaitForThisSample=DelayFromSampleRate;
ctl->sample[samplecnt].PCMRegister=0x5A000000 | ((FreqDividerPCM)<<12) | FreqFractionnalPCM;
//@0
cbp->info = 0;//BCM2708_DMA_WAIT_RESP|BCM2708_DMA_NO_WIDE_BURSTS;//BCM2708_DMA_NO_WIDE_BURSTS /*| BCM2708_DMA_WAIT_RESP | */;
cbp->src = mem_virt_to_phys(&ctl->GpioDebugSampleRate); //Clear
if(Instrumentation==1)
cbp->dst = phys_gpio_clear_addr;
else
cbp->dst = dummy_gpio;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
//@1
//@0
//Set Amplitude by writing to PWM_SERIAL via PADS
cbp->info = 0;//BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = mem_virt_to_phys(&ctl->sample[samplecnt].Amplitude1);
@ -365,7 +333,7 @@ int SetupGpioClock(uint32_t SymbolRate,double TuningFrequency)
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
//@2
//@1
//Set Amplitude by writing to PWM_SERIAL via Patern
cbp->info = 0;//BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
cbp->src = mem_virt_to_phys(&ctl->sample[samplecnt].Amplitude2);
@ -377,80 +345,25 @@ int SetupGpioClock(uint32_t SymbolRate,double TuningFrequency)
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
//@3
//2
//Set PWMFrequency
cbp->info =/*BCM2708_DMA_NO_WIDE_BURSTS |BCM2708_DMA_WAIT_RESP|*/BCM2708_DMA_SRC_INC;
cbp->info =/*BCM2708_DMA_NO_WIDE_BURSTS*/ BCM2708_DMA_SRC_INC|BCM2708_DMA_NO_WIDE_BURSTS;
// BCM2708_DMA_WAIT_RESP : without 160ns, with 300ns
cbp->src = mem_virt_to_phys(&ctl->sample[samplecnt].FrequencyTab[0]);
if(UsePCMClk==0)
cbp->dst = phys_pwm_clock_div_addr;
if(UsePCMClk==1)
cbp->dst = phys_clock_div_addr;
cbp->length = 4;//mem_virt_to_phys(&ctl->sample[samplecnt].PWMF1); //Be updated by main DMA
cbp->length = 4; //Be updated by main DMA
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
//@4
cbp->info =0;// BCM2708_DMA_WAIT_RESP|BCM2708_DMA_NO_WIDE_BURSTS ; //A
cbp->src = mem_virt_to_phys(&ctl->GpioDebugSampleRate); //Set
if(Instrumentation==1)
cbp->dst = phys_gpio_set_addr;
else
cbp->dst = dummy_gpio;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
//@5
//SET PCM_FIFO TO WAIT
/*cbp->info = 0;//BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP|BCM2708_DMA_D_DREQ |BCM2708_DMA_PER_MAP(2);
cbp->src = mem_virt_to_phys(virtbase); //Dummy DATA
cbp->dst = dummy_gpio;//phys_pcm_fifo_addr;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;*/
}
cbp--;
cbp->next = mem_virt_to_phys((void*)virtbase);
// *************************************** DMA CHANNEL 2 : PWM FREQUENCY *********************************************
// !!!!!!!!!!!!!!!!!!!!!!!!!!!! NOT USED ANYMORE ************************************************************
cbp = ctl->cbdma2;
//printf("DMA2 %x\n",mem_virt_to_phys(&ctl->cb[NUM_CBS_MAIN]));
gpioSetMode(17,1); // OSCILO SUR PIN 17
ctl->GpioDebugPWMF=1<<17; // GPIO 17/ PIN 11 HEADER IS DEBUG SIGNAL OF PWMFREQUENCY
//@0 = CBS_MAIN+0 1280 ns for 2 instructions
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS /*| BCM2708_DMA_WAIT_RESP | */;
cbp->src = mem_virt_to_phys(&ctl->GpioDebugPWMF); //Clear
cbp->dst = phys_gpio_set_addr;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
//@1 = CBS_MAIN+1 Length*27ns
cbp->info =BCM2708_DMA_WAIT_RESP |/*BCM2708_DMA_NO_WIDE_BURSTS| BCM2708_DMA_WAIT_RESP|*//*(0x8<< 21) |*/ BCM2708_DMA_SRC_INC;
cbp->src = mem_virt_to_phys(&ctl->SharedFrequencyTab[0]);//mem_virt_to_phys(&ctl->SharedFrequencyTab[0]);//mem_virt_to_phys(&ctl->SharedFrequency1);
cbp->dst = phys_pwm_clock_div_addr;
cbp->length = ctl->sample[0].PWMF1; //Be updated by main DMA
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
//@2 = CBS_MAIN+2
//** PWM LOW
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS /*| BCM2708_DMA_WAIT_RESP |*/ ; //A
cbp->src = mem_virt_to_phys(&ctl->GpioDebugPWMF); //Set
cbp->dst = phys_gpio_clear_addr;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(ctl->cbdma2); // Loop to begin of DMA 2
// ------------------------------ END DMA INIT ---------------------------------
dma_reg[DMA_CS+DMA_CHANNEL*0x40] = BCM2708_DMA_RESET;
@ -461,18 +374,7 @@ int SetupGpioClock(uint32_t SymbolRate,double TuningFrequency)
udelay(100);
dma_reg[DMA_DEBUG+DMA_CHANNEL*0x40] = 7; // clear debug error flags
udelay(100);
// START DMA will be later when data coming in
//dma_reg[DMA_CS+DMA_CHANNEL*0x40] = 0x10FF0001; // go, mid priority, wait for outstanding writes :7 Seems Max Priorit
//WAIT FOR OUTSTADING_WRITE make 50ns de plus pour ecrire dans un registre
//printf("END INIT SSTV\n");
/*dma_reg[DMA_CS+DMA_CHANNEL_PWMFREQUENCY*0x40] = BCM2708_DMA_RESET;
udelay(1000);
dma_reg[DMA_CS+DMA_CHANNEL_PWMFREQUENCY*0x40] = BCM2708_DMA_INT | BCM2708_DMA_END;
udelay(100);
dma_reg[DMA_CONBLK_AD+DMA_CHANNEL_PWMFREQUENCY*0x40]=mem_virt_to_phys((void *)(ctl->cbdma2) );
udelay(100);
dma_reg[DMA_DEBUG+DMA_CHANNEL_PWMFREQUENCY*0x40] = 7; // clear debug error flags
*/
return 1;
}
@ -514,36 +416,24 @@ void IQToFreqAmp(int I,int Q,double *Frequency,int *Amp,int SampleRate)
}
// A utility function to swap to integers
void swap (uint32_t *a, uint32_t *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
// A function to generate a random permutation of arr[]
void randomize ( uint32_t arr[], int n )
{
// Use a different seed value so that we don't get same
// result each time we run this program
srand ( time(NULL) );
// Start from the last element and swap one by one. We don't
// need to run for the first element that's why i > 0
int i;
for ( i = n-1; i > 0; i--)
{
// Pick a random index from 0 to i
int j = rand() % (i+1);
// Swap arr[i] with the element at random index
swap(&arr[i], &arr[j]);
}
}
inline void shuffle_int(uint32_t list[], size_t len)
{
int j;
uint32_t tmp;
while(len)
{
j = rand() % (len+1);
if (j != len - 1)
{
tmp = list[j];
list[j] = list[len - 1];
list[len - 1] = tmp;
}
len--;
}
}
inline void FrequencyAmplitudeToRegister(double TuneFrequency,uint32_t Amplitude,int NoSample,uint32_t WaitNanoSecond,uint32_t SampleRate,char NoUsePWMF,int debug)
{
@ -559,10 +449,8 @@ inline void FrequencyAmplitudeToRegister(double TuneFrequency,uint32_t Amplitude
0xAAAA8000,0xAAAAA000,0xAAAAA800,0xAAAAAA00,
0xAAAAAA80,0xAAAAAAA0,0xAAAAAAA8,0xAAAAAAAA,0xAAAAAAAA};
static double FixedNumberStepForGpio=(1280.0)/27.0; // Gpio set is 1280ns, Wait is Number of 27ns
#define STEP_AVERAGE_AMPLITUDE 1000
static uint32_t HistoryAmplitude[STEP_AVERAGE_AMPLITUDE];
static uint32_t OldAmplitude=0;
static char First=1;
ctl = (struct control_data_s *)virtbase; // Struct ctl is mapped to the memory allocated by RpiDMA (Mailbox)
@ -576,27 +464,9 @@ inline void FrequencyAmplitudeToRegister(double TuneFrequency,uint32_t Amplitude
// WITH DMA_CTL WITHOUT BCM2708_DMA_WAIT_RESP
// Time = NBStep * 157 ns + 1360 ns
#define FREQ_MINI_TIMING 157
#define FREQ_DELAY_TIME 0
//#define PWMF_MARGIN 2700 //A Margin for now at 1us with PCM
//#define PWMF_MARGIN 2400 //A Margin for now at 1us with PCM ->OK
#define PWMF_MARGIN 2198 // Seems to work well with SSTV
#define PWM_STEP_MAXI 200
// WITH BCM2708_DMA_WAIT_RESP
// Time = NBStep * 420 ns + 420 ns
// GOOD BY EXPERIMENT
/*#define FREQ_MINI_TIMING 500
#define FREQ_DELAY_TIME 500
#define PWMF_MARGIN (1000) //A Margin for now at 1us
#define PWM_STEP_MAXI 200
*/
/*#define FREQ_MINI_TIMING 420
#define FREQ_DELAY_TIME 0
#define PWMF_MARGIN (3000) //A Margin for now at 1us
#define PWM_STEP_MAXI 200
*/
if(WaitNanoSecond==0)
{
if(SampleRate!=0)
@ -604,19 +474,8 @@ inline void FrequencyAmplitudeToRegister(double TuneFrequency,uint32_t Amplitude
}
PwmNumberStep=WaitNanoSecond/FREQ_MINI_TIMING;
//if((PwmNumberStep%2)!=0) PwmNumberStep++; // Paire
/*
if(WaitNanoSecond<FREQ_DELAY_TIME) SkipFrequency=1; else SkipFrequency=0;
if(WaitNanoSecond>(FREQ_DELAY_TIME+PWMF_MARGIN))
PwmNumberStep=(WaitNanoSecond-FREQ_DELAY_TIME-PWMF_MARGIN)/FREQ_MINI_TIMING;
else
PwmNumberStep=2; // Mini
*/
if(PwmNumberStep>PWM_STEP_MAXI) PwmNumberStep=PWM_STEP_MAXI;
//PwmNumberStep=100;
//printf("Waitnano %d NbStep=%d\n",WaitNanoSecond,PwmNumberStep);
// ********************************** PWM FREQUENCY PROCESSING *****************************
@ -630,8 +489,6 @@ inline void FrequencyAmplitudeToRegister(double TuneFrequency,uint32_t Amplitude
uint32_t FreqDividerf1=(FreqFractionnalf2!=4095)?FreqDividerf2:FreqDividerf2+1;
uint32_t FreqFractionnalf1=(FreqFractionnalf2!=4095)?FreqFractionnalf2+1:0;
//FreqDividerf2=FreqDividerf2*2;//debug
double f1=PllUsed/(FreqDividerf1+(double)FreqFractionnalf1/4096.0);
double f2=PllUsed/(FreqDividerf2+(double)FreqFractionnalf2/4096.0); // f2 is the higher frequency
double FreqTuningUp=PllUsed/(FreqDividerf2+(double)FreqFractionnalf2/4096.0);
@ -667,7 +524,7 @@ inline void FrequencyAmplitudeToRegister(double TuneFrequency,uint32_t Amplitude
NbF2=0;
NbF1F2=0;
//if(CompteurDebug%2000==0) printf("PwmNumberStep %d PWMFrequency %d\n",PwmNumberStep,PWMFrequency);
int AdaptPWMFrequency;
if((PwmNumberStep-PWMFrequency-(PWMF_MARGIN+FREQ_DELAY_TIME)/FREQ_MINI_TIMING)>PwmNumberStep/2)
{
@ -676,7 +533,7 @@ inline void FrequencyAmplitudeToRegister(double TuneFrequency,uint32_t Amplitude
AdaptPWMFrequency=PWMFrequency;
NbF1=0;
NbF2=(PWMF_MARGIN+FREQ_DELAY_TIME)/FREQ_MINI_TIMING;
//NbF2=0;
}
else // SWAP F1 AND F2
{
@ -684,13 +541,13 @@ inline void FrequencyAmplitudeToRegister(double TuneFrequency,uint32_t Amplitude
RegisterF2=0x5A000000 | (FreqDividerf1<<12) | (FreqFractionnalf1);
RegisterF1=0x5A000000 | (FreqDividerf2<<12) | (FreqFractionnalf2);
AdaptPWMFrequency=PwmNumberStep-PWMFrequency;
NbF1=0;//(PWMF_MARGIN+FREQ_DELAY_TIME)/FREQ_MINI_TIMING;
NbF1=0;
NbF2=(PWMF_MARGIN+FREQ_DELAY_TIME)/FREQ_MINI_TIMING;
}
i=0;
NbF1F2=NbF1+NbF2;
//if((CompteurDebug%DEBUG_RATE)==0) printf("F1 %d \n",AdaptPWMFrequency);
if(NoUsePWMF==1)
{
RegisterF1=0x5A000000 | (FreqDividerf1<<12) | (FreqFractionnalf1);
@ -716,46 +573,22 @@ inline void FrequencyAmplitudeToRegister(double TuneFrequency,uint32_t Amplitude
}
}
if (Randomize)
randomize(ctl->sample[NoSample].FrequencyTab,i);
shuffle_int(ctl->sample[NoSample].FrequencyTab,i);
//SHould finished by F2
ctl->sample[NoSample].FrequencyTab[i++]=RegisterF2;
NbF2++;
NbF1F2++;
}
//if((CompteurDebug%DEBUG_RATE)==0) printf("NbF1=%d NbF2=%d i=%d\n",NbF1,NbF2,i);
cbpwrite=cbp+3;
cbpwrite=cbp+2;
cbpwrite->length=i*4;
//ctl->sample[NoSample].PWMF1=i*4;//((PWMFrequency-FixedNumberStepForGpio)/4)*4;
//ctl->sample[NoSample].PWMF2=0;
// ****************************** AMPLITUDE PROCESSING **********************************************
// ---------------- MAKE AN AVERAGE AMPLITUDE ---------------------
/*
if(First==1)
{
memset(HistoryAmplitude,0,STEP_AVERAGE_AMPLITUDE*sizeof(uint32_t));
First=0;
}
memcpy(HistoryAmplitude,HistoryAmplitude+1,(STEP_AVERAGE_AMPLITUDE-1)*sizeof(uint32_t));
HistoryAmplitude[STEP_AVERAGE_AMPLITUDE-1]=Amplitude;
static uint32_t AverageAmplitude;
static int StepAmplitude;
AverageAmplitude=0;
for(StepAmplitude=0;StepAmplitude<STEP_AVERAGE_AMPLITUDE;StepAmplitude++)
AverageAmplitude+= HistoryAmplitude[StepAmplitude];
if((NoSample%STEP_AVERAGE_AMPLITUDE)==0)
{
Amplitude=AverageAmplitude/STEP_AVERAGE_AMPLITUDE;
OldAmplitude=Amplitude;
}
else
Amplitude=OldAmplitude;
*/
Amplitude=(Amplitude>32767)?32767:Amplitude;
int IntAmplitude=(Amplitude*7.0)/32767.0; // Convert to 8 amplitude step
@ -784,103 +617,136 @@ inline void FrequencyAmplitudeToRegister(double TuneFrequency,uint32_t Amplitude
static int OldIntAmplitude=0;
/*if(((OldIntAmplitude!=0)&&(IntAmplitude==0))||((OldIntAmplitude==0)&&(IntAmplitude!=0)))
{
cbpwrite=cbp+1;
cbpwrite->next=mem_virt_to_phys(cbpwrite + 1); //Set Patern
}
else
{
cbpwrite=cbp+1;
cbpwrite->next=mem_virt_to_phys(cbpwrite + 2); //DOn't set patern
}
OldIntAmplitude=IntAmplitude; */
//IntAmplitude=IntAmplitude+3; // Make a little more gain if amplitude not 0
if(IntAmplitude>7) IntAmplitude=7;
//printf("%d\n",IntAmplitude);
ctl->sample[NoSample].Amplitude1=0x5a000000 + (IntAmplitude&0x7) + (1<<4) + (0<<3); // Set output power for I/Q GPIO18/GPIO19;//TEST +1
ctl->sample[NoSample].Amplitude1=0x5a000000 + (IntAmplitude&0x7) + (1<<4) + (0<<3);
static uint32_t phys_pwm_fifo_addr = 0x7e20c000 + 0x18;//PWM Fifo
static uint32_t dummy_gpio = 0x7e20b000;
static uint32_t phys_gpio_pads_addr =0x7e10002c;
/*
cbpwrite=cbp+1;
cbpwrite->dst= phys_gpio_pads_addr;
cbpwrite=cbp+2;
cbpwrite->dst=phys_pwm_fifo_addr;
*/
// ****************************** WAIT PROCESSING **********************************************
if(WaitNanoSecond!=0) //ModeRF
{
/*if(WaitNanoSecond<PWMF_MARGIN) // Skip Frequency setting, just waiting
{
cbp->next=mem_virt_to_phys(cbp + 6);
printf("WaitNano Mini %d\n",WaitNanoSecond);
}
else
cbp->next=mem_virt_to_phys(cbp + 1);
*/
static uint32_t NbRepeat;
static int Relicat=0;
NbRepeat=WaitNanoSecond/DelayFromSampleRate; // 1GHZ/(SAMPLERATE*NbStepPCM)
Relicat+=(WaitNanoSecond%DelayFromSampleRate);
if(Relicat>=DelayFromSampleRate)
{
Relicat=Relicat-DelayFromSampleRate;
NbRepeat+=1;
}
if((DelayFromSampleRate+Relicat)<0)
{
Relicat=DelayFromSampleRate+Relicat;
NbRepeat-=1;
}
//static uint32_t NbRepeat=1;
// cbpwrite=cbp+5; // Set a repeat to wait PCM
// cbpwrite->length=4*(NbRepeat); //-> OK
//printf("NbRepeat %d Relicat %d WaitNanoSecond%d DelayFromSampleRate%d\n",NbRepeat,Relicat,WaitNanoSecond,DelayFromSampleRate);
}
}
// Call ntp_adjtime() to obtain the latest calibration coefficient.
void update_ppm(double ppm)
int GetDMADelay(int Step)
{
//Calibrate DMA Rate
// =====================================================
static volatile uint32_t cur_cb,last_cb;
struct timespec gettime_now;
int32_t start_time,time_difference;
int last_sample;
int this_sample;
int free_slots;
dma_cb_t *cbp = ctl->cb;
cur_cb = (uint32_t)virtbase; // DMA AT 1st CBS
dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]=mem_virt_to_phys((void*)cur_cb);
usleep(100);
int samplecnt;
for (samplecnt = 0; samplecnt < NUM_SAMPLES ; samplecnt++)
{
cbp+=2;
cbp->length = (uint32_t)4L*Step;
cbp++;
}
dma_reg[DMA_CS+DMA_CHANNEL*0x40] = DMA_CS_PRIORITY(7) | DMA_CS_PANIC_PRIORITY(7) | DMA_CS_DISDEBUG |DMA_CS_ACTIVE; // START DMA : go, mid priority, wait for outstanding writes :7 Seems Max Priority
usleep(5000); //Wait to be sure DMA is running stable
int i;
int SumDelay=0;
for(i=0;i<10;i++)
{
last_cb = mem_phys_to_virt((uint32_t)(dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]));
last_sample = (last_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) * CBS_SIZE_BY_SAMPLE);
clock_gettime(CLOCK_REALTIME, &gettime_now);
start_time = gettime_now.tv_nsec;
// ONE SAMPLE SHOULD BE MINIMUM AROUND Time = NBStep * 157 ns + 1360 ns +1360*4 ns = 6us and MAX 200*157+1360*5 = 35us
// Sleep at 80% de DELAY*NUM_SAMPLE
// BY removing 2 CBP = 300ns gain
do
{
usleep(10);
cur_cb = mem_phys_to_virt((uint32_t)(dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]));
this_sample = (cur_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) * CBS_SIZE_BY_SAMPLE);
free_slots = this_sample - last_sample;
if (free_slots < 0) // WARNING : ORIGINAL CODE WAS < strictly
free_slots += NUM_SAMPLES;
clock_gettime(CLOCK_REALTIME, &gettime_now);
}
while(free_slots<=NUM_SAMPLES*0.6);
time_difference = gettime_now.tv_nsec - start_time;
if(time_difference<0) time_difference+=1E9;
//printf("Delay = %d\n",time_difference/free_slots);
SumDelay+=time_difference/free_slots;
}
//STop DMA
dma_reg[DMA_CS+DMA_CHANNEL*0x40] |= DMA_CS_ABORT;//BCM2708_DMA_INT | BCM2708_DMA_END;
udelay(100);
dma_reg[DMA_CS+DMA_CHANNEL*0x40]&= ~DMA_CS_ACTIVE;
dma_reg[DMA_CS+DMA_CHANNEL*0x40] |= DMA_CS_RESET; //BCM2708_DMA_ABORT|BCM2708_DMA_RESET;
udelay(100);
return SumDelay/10;
}
int CalibrateSystem(int *ppm,int *BaseDelayDMA,int *StepDelayDMA)
{
struct timex ntx;
int status;
double ppm_new;
//Calibrate Clock system (surely depends also on PLL PPM
// =====================================================
ntx.modes = 0; /* only read */
status = ntp_adjtime(&ntx);
status = ntp_adjtime(&ntx);
double clockppm;
if (status != TIME_OK) {
//cerr << "Error: clock not synchronized" << endl;
//return;
}
if (status != TIME_OK)
{
printf("Error: NTP\n");
return 0;
}
clockppm = (double)ntx.freq/(double)(1 << 16);
if(abs(clockppm)<200)
*ppm=clockppm;
//printf("Clock PPM = %f\n",ppm);
int i;
int BaseDelay=0;
BaseDelay=GetDMADelay(0);
ppm_new = (double)ntx.freq/(double)(1 << 16); /* frequency scale */
if (abs(ppm_new)>200) {
printf( "Warning: absolute ppm value is greater than 200 and is being ignored!\n");
} else {
if (ppm!=ppm_new) {
printf(" Obtained new ppm value: %f\n",ppm_new);
}
ppm=ppm_new;
}
*BaseDelayDMA=BaseDelay;
*StepDelayDMA=(GetDMADelay(PWM_STEP_MAXI/2)-(*BaseDelayDMA))/(PWM_STEP_MAXI/2);
//for(i=1;i<200;i+=10)
//printf("Step %d =%d\n",i,(GetDMADelay(i)-BaseDelay)/i);
return 1;
}
int pitx_init(int SampleRate, double TuningFrequency, int* skipSignals)
{
int pitx_init(int SampleRate, double TuningFrequency, int* skipSignals,int SetDma)
{
InitGpio();
InitDma(terminate, skipSignals);
if(SetDma) DMA_CHANNEL=SetDma;
SetupGpioClock(SampleRate,TuningFrequency);
//int FREQ_MINI_TIMING=157;
//int PWMF_MARGIN = 1120; //A Margin for now at 1us with PCM ->OK
if(CalibrateSystem(&globalppmpll,&PWMF_MARGIN,&FREQ_MINI_TIMING))
printf("Calibrate : ppm=%d DMA %dns:%dns\n",globalppmpll,FREQ_MINI_TIMING,PWMF_MARGIN);
//printf("Timing : 1 cyle=%dns 1sample=%dns\n",NBSAMPLES_PWM_FREQ_MAX*400*3,(int)(1e9/(float)SampleRate));
return 1;
}
@ -907,6 +773,8 @@ PROGRAM_VERSION);
} /* end function print_usage */
double GlobalTuningFrequency;
int HarmonicNumber =1;
@ -968,10 +836,10 @@ int main(int argc, char* argv[])
float SetFrequency=1e6;//1MHZ
float ppmpll=0.0;
char NoUsePwmFrequency=0;
int SetDma=0;
while(1)
{
a = getopt(argc, argv, "i:f:m:s:p:hld:w:c:r");
a = getopt(argc, argv, "i:f:m:s:p:hld:w:c:ra:");
if(a == -1)
{
@ -1009,7 +877,7 @@ int main(int argc, char* argv[])
case 'l': // loop mode
loop_mode_flag = 1;
break;
case 'd': // loop mode
case 'd': // Dma Sample Burst
DmaSampleBurstSize = atoi(optarg);
NUM_SAMPLES=4*DmaSampleBurstSize;
break;
@ -1025,6 +893,15 @@ int main(int argc, char* argv[])
Randomize=1;
break;
case 'a': // DMA Channel 1-14
if((atoi(optarg)>0)&&(atoi(optarg)<15))
{
SetDma=atoi(optarg);
//DMA_CHANNEL=SetDma; Should be set after initdma
}
else
SetDma=0;
break;
case -1:
break;
case '?':
@ -1063,18 +940,19 @@ int main(int argc, char* argv[])
}
resetFile();
return pitx_run(Mode, SampleRate, SetFrequency, ppmpll, NoUsePwmFrequency, readFile, resetFile, NULL);
return pitx_run(Mode, SampleRate, SetFrequency, ppmpll, NoUsePwmFrequency, readFile, resetFile, NULL,SetDma);
}
int pitx_run(
const char Mode,
int SampleRate,
const float SetFrequency,
const float ppmpll,
float ppmpll,
const char NoUsePwmFrequency,
ssize_t (*readWrapper)(void *buffer, size_t count),
void (*reset)(void),
int* skipSignals)
int* skipSignals,
int SetDma)
{
int i;
//char pagemap_fn[64];
@ -1099,7 +977,7 @@ int pitx_run(
fprintf(stdout,"rpitx Version %s compiled %s (F5OEO Evariste) running on ",PROGRAM_VERSION,__DATE__);
// Init Plls Frequency using ppm (or default)
if(ppmpll!=0) ppmpll=(float)globalppmpll; // Use calibrate only if not setting by user
PllFreq500MHZ=PLL_FREQ_500MHZ;
PllFreq500MHZ+=PllFreq500MHZ * (ppmpll / 1000000.0);
@ -1123,7 +1001,7 @@ int pitx_run(
if((Mode==MODE_RF)||(Mode==MODE_RFA))
{
//TabRfSample=malloc(DmaSampleBurstSize*sizeof(samplerf_t));
SampleRate=100000L; //NOT USED BUT BY CALCULATING TIMETOSLEEP IN RF MODE
SampleRate=50000L; //NOT USED BUT BY CALCULATING TIMETOSLEEP IN RF MODE
}
if(Mode==MODE_VFO)
SampleRate=50000L; //50000 BY EXPERIMENT
@ -1138,7 +1016,7 @@ int pitx_run(
pitx_SetTuneFrequency(SetFrequency*1000.0);
pitx_init(SampleRate, GlobalTuningFrequency, skipSignals);
pitx_init(SampleRate, GlobalTuningFrequency, skipSignals,SetDma);
static volatile uint32_t cur_cb,last_cb;
@ -1178,7 +1056,12 @@ int pitx_run(
if(Init==0)
{
TimeToSleep=(1e6*(NUM_SAMPLES-free_slots*2))/SampleRate; // Time to sleep in us
if((Mode==MODE_RF)||(Mode==MODE_RFA))
{
TimeToSleep=100; //Max 100KHZ
}
else
TimeToSleep=(1e6*(NUM_SAMPLES-free_slots*2))/SampleRate; // Time to sleep in us
//printf("TimeToSleep%d\n",TimeToSleep);
}
else
@ -1232,7 +1115,8 @@ int pitx_run(
//dma_reg[DMA_CS+DMA_CHANNEL_PWMFREQUENCY*0x40] = 0x10880001;
//Start Main DMA
dma_reg[DMA_CS+DMA_CHANNEL*0x40] = 0x10FF0001; // go, mid priority, wait for outstanding writes :7 Seems Max Priority
dma_reg[DMA_CS+DMA_CHANNEL*0x40] = DMA_CS_PRIORITY(7) | DMA_CS_PANIC_PRIORITY(7) | DMA_CS_DISDEBUG |DMA_CS_ACTIVE;
Init=0;
@ -1386,7 +1270,7 @@ int pitx_run(
{
// SHOULD NOT EXEED 200 STEP*500ns; SAMPLERATE SHOULD BE MAX TO HAVE PRECISION FOR PCM
// BUT FIFO OF PCM IS 16 : SAMPLERATE MAYBE NOT EXCESS 16*80000 ! CAREFULL BUGS HERE
#define MAX_DELAY_WAIT 25000
#define MAX_DELAY_WAIT (PWM_STEP_MAXI/2*FREQ_MINI_TIMING-PWMF_MARGIN)
static int CompteSample=0;
static uint32_t TimeRemaining=0;
static samplerf_t SampleRf;

Wyświetl plik

@ -2,7 +2,7 @@
#define RPITX_H
#include <ctype.h>
int pitx_init(int SampleRate, double TuningFrequency, int* skipSignals);
int pitx_init(int SampleRate, double TuningFrequency, int* skipSignals,int SetDma);
int pitx_SetTuneFrequencyu(uint32_t Frequency);
#define MODE_IQ 0
@ -21,7 +21,8 @@ int pitx_run(
ssize_t (*readWrapper)(void *buffer, size_t count),
// Wrapper to reset file for looping
void (*reset)(void),
int* skipSignals
int* skipSignals,
int SetDma
);