F5OEO-rpidatv/src/rpidatv.c

2035 wiersze
57 KiB
C

/*
<rpidatv is a software which use the GPIO of Raspberry Pi to transmit Digital Television over HF>
Copyright (C) 2015 Evariste COURJAUD F5OEO (evaristec@gmail.com)
Transmitting on HF band is surely not permitted without license (Hamradio for example).
Usage of this software is not the responsability of the author.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Thanks to first test of RF with Pifm by Oliver Mattos and Oskar Weigl
INSPIRED BY THE IMPLEMENTATION OF PIFMDMA by Richard Hirst <richardghirst@gmail.com> December 2012
Thanks to Brian Jordan G4EWJ for Channel modulation implementation (dvbsenco)
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <stdint.h>
#include <math.h>
#include <time.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "fec100.h"
#include "mailbox.h"
#include <getopt.h>
#include <termios.h> //Used for UART
#include "rpigpio.h"
#include "rpidma.h"
#include <pthread.h>
#include <sys/prctl.h>
#include <sys/timex.h>
#include <sys/ioctl.h>
extern void dvbsenco_init (void) ;
extern uchar* dvbsenco (uchar*) ;
extern void energy (uchar* input,uchar *output) ;
extern void reed (uchar *input188) ;
extern uchar* interleave (uchar* packetin) ;
#define PROGRAM_VERSION "2.0.0"
//Minimum Time in us to sleep
#define KERNEL_GRANULARITY 10000
#define SCHED_PRIORITY 30 //Linux scheduler priority. Higher = more realtime
#define WITH_MEMORY_BUFFER
#define PLLFREQ_PCM 1000000000 // PLLD is running at 500MHz
#define PLL_PCM 0x6
//#define PLLFREQ_PWM 1000000000 //PLLC = 1GHZ , 1.2GHZ ON PIZERO ! But Unstable -> Go back to PLL_D
//#define PLL_PWM 0x5
#define PLLFREQ_PWM 1000000000 //PLLC = 1GHZ , 1.2GHZ ON PIZERO ! But Unstable -> Go back to PLL_D
#define PLL_PWM 0x6
#define PLLFREQ_192 19200000 //PLLA = 19.2MHZ
#define PLL_192 0x1
#define CARRIERFREQ 100000000 // Carrier frequency is 100MHz
//F5OEO Variable
uint32_t TabIQ[4]={0xCCCCCCCC,0x66666666,0x99999999,0x33333333};//0,-pi/2,pi/2,pi
uint32_t TabIQTest[4]={0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC};//0,-pi/2,pi/2,pi
uint32_t TabIQTestI[4]={0x00110011,0x11111111,0x11111111,0x11111111};
uint32_t TabIQTestQ[4]={0x01010101,0x00000000,0x00000000,0x00000000};
int PinOutput[2]={18,19}; //Output signal I/Q on GPIO pin number
//uint32_t TabIQ[4]={0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF};
int SymbolRate=0;
int FEC=1;
double TuneFrequency=62500000;
unsigned char FreqDivider=2;
//End F5OEO
int uart0_filestream = -1; // Handle to Serial Port for Digithin
char DigithinCommand[]="*A";
pthread_t th1; // Thread filling BigBUffer
char EndOfApp=0;
unsigned char Loop=0;
char *FileName;
int fdts; //Handle in Transport Stream File
static void
udelay(int us)
{
struct timespec ts = { 0, us * 1000 };
nanosleep(&ts, NULL);
}
static void
terminate(int dummy)
{
#ifdef WITH_MEMORY_BUFFER
//pthread_cancel(th1);
EndOfApp=1;
pthread_join(th1, NULL);
#endif
close(fdts);
// SET PTT OFF
gpio_reg[0x28/4]=1<<21; // Set PTT OFF
if (dma_reg)
{
dma_reg[DMA_CS+DMA_CHANNEL*0x40] = BCM2708_DMA_INT | BCM2708_DMA_END;
udelay(100);
dma_reg[DMA_CS+DMA_CHANNEL*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
//clk_reg[PWMCLK_CNTL] = 0x5A000006 | (0 << 9) ;
clk_reg[PWMCLK_CNTL] = 0x5A000000|PLL_PWM;
udelay(500);
clk_reg[PCMCLK_CNTL] = 0x5A000000|PLL_PWM;
udelay(500);
//printf("Resetpcm Done\n");
pwm_reg[PWM_DMAC] = 0;
udelay(100);
pwm_reg[PWM_CTL] = PWMCTL_CLRF;
udelay(100);
pwm_reg[PWM_FIFO]=0L;
//printf("Reset pwm Done\n");
}
if (mbox.virt_addr != NULL) {
unmapmem(mbox.virt_addr, NUM_PAGES * PAGE_SIZE);
printf("Unmapmem Done\n");
mem_unlock(mbox.handle, mbox.mem_ref);
//printf("Unmaplock Done\n");
mem_free(mbox.handle, mbox.mem_ref);
//printf("Unmapfree Done\n");
}
//munmap(virtbase,NUM_PAGES * PAGE_SIZE);
printf("END OF RPIDATV\n");
exit(1);
}
static void
fatal(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
terminate(0);
}
#define DATA_FILE_SIZE 4080 // Not used anymore
void setSchedPriority(int priority) {
//In order to get the best timing at a decent queue size, we want the kernel to avoid interrupting us for long durations.
//This is done by giving our process a high priority. Note, must run as super-user for this to work.
struct sched_param sp;
sp.sched_priority=priority;
int ret;
if ((ret = pthread_setschedparam(pthread_self(), SCHED_RR, &sp))) {
printf("Warning: pthread_setschedparam (increase thread priority) returned non-zero: %i\n", ret);
}
/*
if ((ret = pthread_setschedparam(th1, SCHED_RR, &sp))) {
printf("Warning: pthread_setschedparam (increase thread priority) returned non-zero: %i\n", ret);
}
*/
}
/*
void shift(char* window, int len) {
int i;
for (i = 1; i < len; ++i) {
window[i-1] = window[i];
}
window[len-1] = 0;
}
*/
void SetUglyFrequency(double Frequency)
{
int harmonic;
double FreqFound;
uint16_t FreqFractionnal=0;
for(harmonic=1;(harmonic<41);harmonic+=2)
{
//printf("->%lf harmonic %d\n",(Frequency/(double)harmonic),harmonic);
if((Frequency/(double)harmonic)<=(double)PLLFREQ_PWM/8.0) break;
}
harmonic-=2;
//do
{
harmonic+=2;
FreqFound = (double) (Frequency*4.0/(double)harmonic);
FreqDivider=(int) ((double)PLLFREQ_PWM/FreqFound);
FreqFractionnal=4096.0 * (((double)PLLFREQ_PWM/FreqFound)-FreqDivider);
//printf("Ecart = %lf\n", (PLLFREQ/(double)FreqDivider)-(PLLFREQ/(double)(FreqDivider+1.0)));
}
//while((PLLFREQ/(double)FreqDivider)-(PLLFREQ/(double)(FreqDivider+1.0))>25e6); // To Avoir 25MHZ of MASH : seems not a limit, removed
clk_reg[PWMCLK_DIV] = 0x5A000000 | (FreqDivider<<12) | FreqFractionnal;
printf("Tuning on %lf MHZ (harmonic %d):DIV%d/FRAC%d\n",1e-6*(double)PLLFREQ_PWM*(double)harmonic/(4.0*(FreqDivider+(double) FreqFractionnal/4096.0)),harmonic,FreqDivider,FreqFractionnal);
}
//************************************ INIT MODE UGLY ***********************************************
int InitUgly()
{
char MASH=1;
// SET PTT
gpioSetMode(21,1); // GPIO 21 - PIN 40 is output for PTT
gpio_reg[0x1C/4]=1<<21; // Set PTT ON
SetUglyFrequency(TuneFrequency);
//gpioSetMode(18, 2); /* set to ALT5, PWM1 : RF */
if(PinOutput[0]==18) {gpioSetMode(18, 2);printf("\n Using GPIO 18\n");}; //ALT 5
if(PinOutput[0]==12) {gpioSetMode(12, 4);printf("\n Using GPIO 12\n");} //ALT 0
if(PinOutput[0]==40) gpioSetMode(40, 4); //ALT 0
pwm_reg[PWM_CTL] = 0;
//ALWAYS USE MASH
{
//printf("MASH ENABLE\n");
clk_reg[PWMCLK_CNTL] = 0x5A000000 | (MASH << 9)|PLL_PWM ; //1<<9
//clk_reg[PWMCLK_CNTL] = 0x5A000005 | (1 << 9) ;
}
udelay(300);
clk_reg[PWMCLK_CNTL]= 0x5A000010 | (MASH << 9) | PLL_PWM;
pwm_reg[PWM_RNG1] = 32;// 32 Mandatory for Serial Mode without gap
udelay(100);
pwm_reg[PWM_RNG2] = 32;// 32 Mandatory for Serial Mode without gap
udelay(100);
pwm_reg[PWM_DMAC] = PWMDMAC_ENAB | PWMDMAC_THRSHLD;
udelay(100);
pwm_reg[PWM_CTL] = PWMCTL_CLRF;
udelay(100);
//------------------- Init PCM ------------------
pcm_reg[PCM_CS_A] = 1; // Disable Rx+Tx, Enable PCM block
udelay(100);
clk_reg[PCMCLK_CNTL] = 0x5A000000|PLL_PWM; // Source=PLLD (500MHz) //Seems Both should be on same PLL
udelay(1000);
int NbStep;
int prescale=2;
if(SymbolRate>=250)
{
clk_reg[PCMCLK_DIV] = 0x5A000000 | (8<<12); // Set pcm div to 2, giving 250MHz step
NbStep= PLLFREQ_PCM/(8*SymbolRate*1000) -1;
}
else
{
prescale=4*(250/SymbolRate);
clk_reg[PCMCLK_DIV] = 0x5A000000 | ((prescale*2*2)<<12); // Set pcm div to 2, giving 250MHz step
NbStep= PLLFREQ_PCM/(4*prescale*SymbolRate*1000) -1;
printf("Low SymbolRate\n");
}
pcm_reg[PCM_TXC_A] = 0<<31 | 1<<30 | 0<<20 | 0<<16; // 1 channel, 8 bits
udelay(100);
printf("Nb PCM STEP (<1000):%d\n",NbStep);
pcm_reg[PCM_MODE_A] = NbStep<<10; // SHOULD NOT EXCEED 1000 !!!
udelay(100);
pcm_reg[PCM_CS_A] |= 1<<4 | 1<<3; // Clear FIFOs
udelay(100);
pcm_reg[PCM_DREQ_A] = 64<<24 | /*64<<8 |*/ 64<<8 ; //TX Fifo PCM=64 DMA Req when one slot is free?
udelay(100);
pcm_reg[PCM_CS_A] |= 1<<9; // Enable DMA
udelay(1000);
clk_reg[PCMCLK_CNTL] = 0x5A000010 |PLL_PWM; // Source=PLLD and enable
printf("RealSR= %lu Symbol/s \n",PLLFREQ_PCM/((NbStep+1)*4L*prescale));
// ========================== INIT DMA ================================================
ctl = (struct control_data_s *)virtbase;
dma_cb_t *cbp = ctl->cb;
uint32_t phys_pwm_fifo_addr = 0x7e20c000 + 0x18;//PWM
uint32_t phys_fifo_addr = (0x00203000 | 0x7e000000) + 0x04; //PCM
//uint32_t dummy_gpio = 0x7e20b000;
int samplecnt;
for (samplecnt = 0; samplecnt < NUM_SAMPLES; samplecnt++) {
// Write a frequency sample
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS /* BCM2708_DMA_WAIT_RESP |BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(5)*/;
cbp->src = mem_virt_to_phys(ctl->sample + samplecnt);
cbp->dst = phys_pwm_fifo_addr;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
//printf("cbp : sample %x src %x dest %x next %x\n",ctl->sample + i,cbp->src,cbp->dst,cbp->next);
cbp++;
// Delay
cbp->info = BCM2708_DMA_SRC_IGNOR |/* 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);
cbp->dst = phys_fifo_addr;//Delay with PCM
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
}
cbp--;
cbp->next = mem_virt_to_phys(virtbase);
// ----------------------------- END DMA ------------------------------------
pwm_reg[PWM_CTL] = PWMCTL_USEF1| PWMCTL_MODE1| PWMCTL_PWEN1|PWMCTL_RPTL1 ; //PWM0
usleep(100);
pcm_reg[PCM_CS_A] |= 1<<2; //START TX PCM
return 1;
}
//************************************ INIT MODE IQ ***********************************************
int InitIQ(int DigithinMode)
{
//PIN FOR I
if(PinOutput[0]==18) gpioSetMode(18, 2); //ALT 5
if(PinOutput[0]==12) gpioSetMode(12, 4); //ALT 0
if(PinOutput[0]==40) gpioSetMode(40, 4); //ALT 0
//PIN FOR Q
if(PinOutput[1]==13) gpioSetMode(13, 4); //ALT 0
if(PinOutput[1]==19) gpioSetMode(19, 2); //ALT 5
if(PinOutput[1]==41) gpioSetMode(41, 4); //ALT 0
if(PinOutput[1]==45) gpioSetMode(45, 4); //ALT 0
/* CAM-GPIO IS ON 41 on B+ : DON'T USE*/
// REMOVE AUTODETECTION PIN FROM PI MODEL - USE PIN MAPPING
/*
if (model<3) //ONLY ON B : FOR SOLDERING on PCB near audio output, ON B+ IT CRASH CAM
{
gpioSetMode(40, 4); // set to ALT0, PWM1 DIGILITE Model B
gpioSetMode(41, 4); // set to ALT0, PWM2 DIGILITE Model B !!! CAM-GPIO IS ON 41 on B+
}
*/
//unsigned int SRClock=PLLFREQ_PCM/(SymbolRate*1000);
// SET PTT
gpioSetMode(21,1); // GPIO 21 - PIN 40 is output for PTT
gpio_reg[0x1C/4]=1<<21; // Set PTT ON
unsigned int SRClock;
//unsigned int SRClockPCM=(PLLFREQ_PCM/(SymbolRate*1000*64))*64;
//SymbolRate = PLLFREQ/(SRClockPCM*1000);
// CLK_DIGITHIN 500MHZ(PLLD)/4MHZ = 125
int CLK_DIGITHIN=PLLFREQ_PCM/4E6;
//#define CLK_4MHZ 125
if(DigithinMode==1)
{
uint32_t DigiThin_ClockBySymbol;
// GPIO4 needs to be ALT FUNC 0 to otuput the clock
gpio_reg[GPFSEL0] = (gpio_reg[GPFSEL0] & ~(7 << 12)) | (4 << 12); //ENABLE CLOCK - In case used by digilite
usleep(1000);
clk_reg[GPCLK_CNTL] = 0x5A << 24 |0<<4 | PLL_PCM;
usleep(1000);
clk_reg[GPCLK_DIV] = 0x5A << 24 | (CLK_DIGITHIN<<12) ; //CLK FREQ = 4MHZ: Fixed for Digithin
usleep(100);
DigiThin_ClockBySymbol=( PLLFREQ_PCM/(CLK_DIGITHIN));
//SRClock=DigiThin_ClockBySymbol*CLK_4MHZ;
printf("Digithin Clock at 4MHZ:%d clock by Symbol (SR=%ld)\n",DigiThin_ClockBySymbol,4000000/(SymbolRate*1000L));
udelay(500);
clk_reg[GPCLK_CNTL] = 0x5A << 24 | 0 << 9 | 1 << 4 | PLL_PCM; //NO MASH !!!
udelay(500);
uart0_filestream = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY); //Open in non blocking read/write mode
if (uart0_filestream == -1)
{
//ERROR - CAN'T OPEN SERIAL PORT
printf("Error - Unable to open UART. Ensure it is not in use by another application\n");
}
//CONFIGURE THE UART
//The flags (defined in /usr/include/termios.h - see http://pubs.opengroup.org/onlinepubs/007908799/xsh/termios.h.html):
struct termios options;
tcgetattr(uart0_filestream, &options);
options.c_cflag = B57600 | CS8 | CLOCAL | CREAD; //<Set baud rate
options.c_iflag = IGNPAR;
options.c_oflag = 0;
options.c_lflag = 0;
tcflush(uart0_filestream, TCIFLUSH);
tcsetattr(uart0_filestream, TCSANOW, &options);
//GPIO7 (pin 26) is connected to the reset pin of the dsPIC, so it should always be high. It may never be necessary to reset the dsPIC, but it gives the option.
// DigiThin UART commands (CRLF not required)
// *0 reboot
// *1 test mode, no mod
// *2 test mode, LSB
// *3 test mode, USB
// *4 test mode, in phase
// *5 test mode, ALT1
// *6 test mode, ALT2
// *7 test mode, ALT4
//
// 4MHz reference clock
//
// *A running, 12 cycles per bit, nominal 333kS
// *B running, 15 cycles per bit, nominal 266kS
// *C running, 18 cycles per bit, nominal 222kS
// *D running, 21 cycles per bit, nominal 190kS
// *E running, 24 cycles per bit, nominal 166kS
// *F running, 27 cycles per bit, nominal 148kS
// *G running, 30 cycles per bit, nominal 133kS
// *H running, 33 cycles per bit, nominal 121kS
//
// *? request status
switch(SymbolRate)
{
case 333:DigithinCommand[1]='A';SymbolRate=333333;break;
case 266:DigithinCommand[1]='B';SymbolRate=266666;break;
case 222:DigithinCommand[1]='C';SymbolRate=222222;break;
case 190:DigithinCommand[1]='D';SymbolRate=190476;break;
case 166:DigithinCommand[1]='E';SymbolRate=166666;break;
case 148:DigithinCommand[1]='F';SymbolRate=148148;break;
case 133:DigithinCommand[1]='G';SymbolRate=133333;break;
case 121:DigithinCommand[1]='H';SymbolRate=121121;break;
default:DigithinCommand[1]='A';SymbolRate=333333;break;
}
SRClock=PLLFREQ_PCM/(SymbolRate);
SymbolRate=SymbolRate/1000;
}
else
{
//#define VCO_MODE
SRClock=PLLFREQ_PCM/(1000*SymbolRate);
#ifdef DIGILITE_CLOCK_MODE
printf("\n ******** DIGILITE CLOCK MODE*********** \n");
printf("SRClok=%d SYmbolRate=%dKSymb\n",SRClock,500000/SRClock);
gpio_reg[GPFSEL0] = (gpio_reg[GPFSEL0] & ~(7 << 12)) | (4 << 12); //ENABLE CLOCK - In case used by digilite
clk_reg[GPCLK_CNTL] = 0x5A << 24 |0<<4 | PLL_PCM;
udelay(2000);
//clk_reg[GPCLK_DIV] = 0x5A << 24 | ((SRClock)<<12) ; //CLK FREQ = SR for Digilite
clk_reg[GPCLK_DIV] = 0x5A << 24 | ((SRClock>>2)<<12) ; //CLK FREQ = SR for F5LGJ
udelay(500);
clk_reg[GPCLK_CNTL] = 0x5A << 24 | 1 << 9 | 1 << 4 | PLL_PCM; //NO MASH !!!
udelay(500);
#endif
#ifdef VCO_MODE
printf("\n ******** VCO CLOCK MODE*********** \n");
uint32_t FreqVCO=437000000;
uint32_t FreqDivider,FreqFractionnal;
FreqDivider=(int) ((double)PLLFREQ_PWM/FreqVCO);
FreqFractionnal=4096.0 * (((double)PLLFREQ_PWM/FreqVCO)-FreqDivider);
FreqDivider=FreqDivider%4096;
FreqFractionnal=FreqFractionnal%4096;
printf("Freq Divider %d Freq Frac %d\n",FreqDivider,FreqFractionnal);
gpio_reg[GPFSEL0] = (gpio_reg[GPFSEL0] & ~(7 << 12)) | (4 << 12); //ENABLE CLOCK - In case used by digilite
clk_reg[GPCLK_CNTL] = 0x5A << 24 |0<<4 | PLL_PWM;
udelay(2000);
clk_reg[GPCLK_DIV] = 0x5A << 24 | (FreqDivider<<12) | FreqFractionnal ; //CLK FREQ = SR for Digilite
udelay(500);
clk_reg[GPCLK_CNTL] = 0x5A << 24 | 1 << 9 | 1 << 4 | PLL_PWM; //MASH !!!
udelay(500);
#endif
}
pwm_reg[PWM_CTL] = 0;
if(SymbolRate<250)
{
SRClock=PLLFREQ_192/(1000*SymbolRate);
clk_reg[PWMCLK_CNTL] = 0x5A000000 | (0 << 9) |PLL_192 ;
udelay(300);
clk_reg[PWMCLK_DIV] = 0x5A000000 | ((SRClock)<<12); //*2: FIXME : Because SRClock is normaly based on 500Mhz not 1GH
udelay(300);
clk_reg[PWMCLK_CNTL] = 0x5A000010 | (0 << 9) | PLL_192;
printf("Real SR = %d KSymbol / Clock Divider =%d \n",PLLFREQ_192/(SRClock*1000),SRClock);
}
else
{
SRClock=PLLFREQ_PCM/(1000*SymbolRate);
clk_reg[PWMCLK_CNTL] = 0x5A000000 | (0 << 9) |PLL_PCM ;
udelay(300);
clk_reg[PWMCLK_DIV] = 0x5A000000 | ((SRClock)<<12); //*2: FIXME : Because SRClock is normaly based on 500Mhz not 1GH
udelay(300);
clk_reg[PWMCLK_CNTL] = 0x5A000010 | (0 << 9) | PLL_PCM;
printf("Real SR = %d KSymbol / Clock Divider =%d \n",PLLFREQ_PCM/(SRClock*1000),SRClock);
}
pwm_reg[PWM_RNG1] = 32;// 32 Mandatory for Serial Mode without gap
udelay(100);
pwm_reg[PWM_RNG2] = 32;// 32 Mandatory for Serial Mode without gap
pwm_reg[PWM_DMAC] = PWMDMAC_ENAB | PWMDMAC_THRSHLD;
udelay(100);
pwm_reg[PWM_CTL] = PWMCTL_CLRF;
udelay(100);
//printf("Playing File =%s at %d KSymbol FEC=%d ",argv[1],PLLFREQ_PCM/SRClock/1000,abs(FEC));
// --------------------- INIT DMA IQ ------------------------------
ctl = (struct control_data_s *)virtbase;
dma_cb_t *cbp = ctl->cb;
uint32_t phys_pwm_fifo_addr = 0x7e20c000 + 0x18;//PWM
int samplecnt;
NUM_SAMPLES = NUM_SAMPLES_MAX/2; // Minize the buffer in IQ Mode
for (samplecnt = 0; samplecnt < NUM_SAMPLES; samplecnt++) {
// Write a PWM sample
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP|BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(5);
cbp->src = mem_virt_to_phys(ctl->sample + samplecnt);
cbp->dst = phys_pwm_fifo_addr;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
//printf("cbp : sample %x src %x dest %x next %x\n",ctl->sample + i,cbp->src,cbp->dst,cbp->next);
cbp++;
}
cbp--;
cbp->next = mem_virt_to_phys(virtbase);
// ------------------------------ END DMA INIT ---------------------------------
pwm_reg[PWM_CTL] = PWMCTL_USEF2|PWMCTL_PWEN2|PWMCTL_MODE2|PWMCTL_USEF1| PWMCTL_MODE1| PWMCTL_PWEN1; //PWM0
return 1;
}
int InitDTX1()
{
int i;
gpioSetMode(2, 1); // D0 GPIO 2 : Header 3
gpioSetMode(3, 1); // D1 GPIO 3 : Header 5
gpioSetMode(4, 1); // D2 GPIO 4 : Header 7
gpioSetMode(14, 1); // D3 GPIO 14 : Header 8
gpioSetMode(15, 1); // D4 GPIO 15 : Header 10
gpioSetMode(17, 1); // D5 GPIO 17 : Header 11
gpioSetMode(18, 1); // D6 GPIO 18 : Header 12
gpioSetMode(27, 1); // D7 GPIO 27 : Header 13
gpioSetMode(22, 1); // CLK GPIO 22 : Header 15
//gpioSetMode(23, 1); // TPCLK GPIO 23 : Header 16
gpioSetMode(24, 1); // TPCLK GPIO 24 : Header 18
/*
for(i=0;i<40000;i++)
{
gpio_reg[0x1C/4]=1<<22;
usleep(100);
gpio_reg[0x28/4]=1<<22;
usleep(100);
}
*/
uint32_t TSRate=SymbolRate*125/*1000/8*/*2*FEC*188/(204*(FEC+1L));
//TSRate=100000;//TEST
uint32_t SRTSClock=PLLFREQ_PCM/(TSRate*2*32); //32 mais SET/CLR *2
// TEST ********************
//SRTSClock=1000/32;
// **************
printf("DTX1 : TS Rate = %lu ClockDiv=%lu\n",(unsigned long int)TSRate,(unsigned long int)SRTSClock);
pwm_reg[PWM_CTL] = 0;
clk_reg[PWMCLK_CNTL] = 0x5A000000 | (0 << 9) |PLL_PCM ;
udelay(600);
clk_reg[PWMCLK_DIV] = 0x5A000000 | ((SRTSClock)<<12); //*2: FIXME : Because SRClock is normaly based on 500Mhz not 1GH
udelay(300);
clk_reg[PWMCLK_CNTL] = 0x5A000010 | (0 << 9) | PLL_PCM;
pwm_reg[PWM_RNG1] = 32;// 32 Mandatory for Serial Mode without gap
udelay(100);
pwm_reg[PWM_RNG2] = 32;// 32 Mandatory for Serial Mode without gap
pwm_reg[PWM_DMAC] = PWMDMAC_ENAB | PWMDMAC_THRSHLD;
udelay(100);
pwm_reg[PWM_CTL] = PWMCTL_CLRF;
udelay(100);
pwm_reg[PWM_CTL] = /*PWMCTL_USEF2|PWMCTL_PWEN2|PWMCTL_MODE2|*/PWMCTL_USEF1| PWMCTL_MODE1| PWMCTL_PWEN1; //PWM
//------------------------- INIT DMA DTX1 --------------------
ctl = (struct control_data_s *)virtbase;
dma_cb_t *cbp = ctl->cb;
uint32_t phys_pwm_fifo_addr = 0x7e20c000 + 0x18;//PWM
uint32_t dummy_gpio = 0x7e20b000;
NUM_SAMPLES = NUM_SAMPLES_MAX/2; // Minize the buffer in DTX1 Mode
for (i = 0; i < NUM_SAMPLES; i++)
{
ctl->sample[i] = 0; // Silence
if((i%2)==0)
{
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP;
cbp->src = mem_virt_to_phys(ctl->sample + i );//Surement WORD1=CLR
cbp->dst = 0x7E200028; //CLEAR BIT
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
//printf("cbp CLEAR : sample %x src %x dest %x next %x\n",ctl->sample + i,cbp->src,cbp->dst,cbp->next);
cbp++;
/*
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP|BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(5);
cbp->src = mem_virt_to_phys(virtbase);
cbp->dst = phys_pwm_fifo_addr;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
//printf("cbp : sample %x src %x dest %x next %x\n",ctl->sample + i,cbp->src,cbp->dst,cbp->next);
cbp++;*/
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS| BCM2708_DMA_WAIT_RESP;
cbp->src = mem_virt_to_phys(virtbase);
cbp->dst = dummy_gpio ;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
//printf("cbp DUMMY: sample %x src %x dest %x next %x\n",ctl->sample + i,cbp->src,cbp->dst,cbp->next);
cbp++;
}
else
{
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP;
cbp->src = mem_virt_to_phys(ctl->sample + i );//Surement WORD1=CLR
cbp->dst = 0x7E20001C; //SET BIT
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
//printf("cbp SET: sample %x src %x dest %x next %x\n",ctl->sample + i,cbp->src,cbp->dst,cbp->next);
cbp++;
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP|BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(5);
cbp->src = mem_virt_to_phys(virtbase);
cbp->dst = phys_pwm_fifo_addr;
cbp->length = 4;
cbp->stride = 0;
cbp->next = mem_virt_to_phys(cbp + 1);
//printf("cbp PWM: sample %x src %x dest %x next %x\n",ctl->sample + i,cbp->src,cbp->dst,cbp->next);
cbp++;
}
}
cbp--;
cbp->next = mem_virt_to_phys(virtbase);
return 1;
}
//#define BIG_BUFFER_SIZE ((int)((NUM_SAMPLES*4*1.5)/188)*188)
#define BIG_BUFFER_SIZE (18800*8*2)
#define BURST_MEM_SIZE (188)
typedef struct circular_buffer
{
unsigned char *buffer;
volatile unsigned int head;
volatile unsigned int tail;
pthread_mutex_t lock;
}ring_buffer;
ring_buffer my_circular_buffer;
int BufferAvailable()
{
int Available= my_circular_buffer.head-my_circular_buffer.tail;
if(Available<0) Available+=BIG_BUFFER_SIZE;
return Available;
}
void store_in_buffer(unsigned char data)
{
while(((unsigned int)(my_circular_buffer.head + 1) % BIG_BUFFER_SIZE)==my_circular_buffer.tail)
usleep(50000);
unsigned int next = (unsigned long)(my_circular_buffer.head + 1) % BIG_BUFFER_SIZE;
my_circular_buffer.buffer[my_circular_buffer.head] = data;
my_circular_buffer.head = next;
}
void store_in_buffer_1880(unsigned char *data)
{
while(((unsigned int)(my_circular_buffer.head + BURST_MEM_SIZE) % BIG_BUFFER_SIZE)==my_circular_buffer.tail)
{
//printf("Bigbuffer plein\n");
usleep(50000);
}
pthread_mutex_lock(&my_circular_buffer.lock);
memcpy(my_circular_buffer.buffer+my_circular_buffer.head,data,BURST_MEM_SIZE);
unsigned int next = (unsigned long)(my_circular_buffer.head + BURST_MEM_SIZE) % BIG_BUFFER_SIZE;
my_circular_buffer.head = next;
pthread_mutex_unlock(&my_circular_buffer.lock);
}
char read_from_buffer()
{
//printf("#\n");
// if the head isn't ahead of the tail, we don't have any characters
while (my_circular_buffer.head == my_circular_buffer.tail)
{
sleep(0);//sched_yield();
}
char data = my_circular_buffer.buffer[my_circular_buffer.tail];
my_circular_buffer.tail = (unsigned int)(my_circular_buffer.tail + 1) % BIG_BUFFER_SIZE;
return data;
}
void read_from_buffer_188(unsigned char *Dest)
{
while(BufferAvailable()<188) {usleep(5000);printf("B");} // Carefull of deadlock ! BE sure to have available
pthread_mutex_lock(&my_circular_buffer.lock);
memcpy(Dest,my_circular_buffer.buffer+my_circular_buffer.tail,188);
my_circular_buffer.tail = (unsigned int)(my_circular_buffer.tail + 188) % BIG_BUFFER_SIZE;
pthread_mutex_unlock(&my_circular_buffer.lock);
}
void *FillBigBuffer (void * arg)
{
char name[16];
static uchar buff188[BURST_MEM_SIZE];
static int ByteRead=0;
static int TotalByteRead=0;
static int NbWrite=0;
memset(name, '\0', sizeof(name));
strcpy(name,"BIGBUFFER");
//pthread_setname_np(pthread_self(), name);
prctl(PR_SET_NAME, name, 0, 0, 0);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
struct stat bufstat;
int ret;
ret=fstat(fdts,&bufstat);
if(S_ISFIFO(bufstat.st_mode))
printf("Using a Pipe\n");
else
printf("Using a File %d %d\n",ret,bufstat.st_mode);
while(EndOfApp==0)
{
TotalByteRead=0;
//usleep(200);
do
{
int n;
if(S_ISFIFO(bufstat.st_mode))
{
do
{
ioctl(fdts, FIONREAD, &n);
if(n<(BURST_MEM_SIZE)) {usleep(10000);}
}
while(n<(BURST_MEM_SIZE));
}
ByteRead=read(fdts,buff188+TotalByteRead,BURST_MEM_SIZE-TotalByteRead);
if(ByteRead<=0)
{
if(Loop==1)
{
close(fdts);
fdts = open(FileName, 'r');
TotalByteRead=0;
printf("Loop %s\n",FileName);
}
else
{
printf("Filling BUffer : EOF\n");
//terminate(0);
close(fdts);
return 0; // END OF FILE
}
}
else
{
if(ByteRead!=(BURST_MEM_SIZE-TotalByteRead))
{
//usleep(25000);
}
TotalByteRead+=ByteRead;
//usleep(2000);
}
}
while (TotalByteRead<BURST_MEM_SIZE); // Read should be around 20us
if(((BIG_BUFFER_SIZE-BufferAvailable())<=BIG_BUFFER_SIZE/8))
{
unsigned char Dummy[188];
if(S_ISFIFO(bufstat.st_mode))
{
printf("PIdatv ov=%d/%d\n",BufferAvailable(),BIG_BUFFER_SIZE);
while(BufferAvailable()>BIG_BUFFER_SIZE/8)
read_from_buffer_188(Dummy);
}
//usleep(1000);
}
//printf("Lock BigBuffer\n");
store_in_buffer_1880(buff188);
//printf("#");
/*
for(NbWrite=0;NbWrite<1880;NbWrite++)
{
store_in_buffer(buff188[NbWrite]);
}
*/
// printf("UNLock BigBuffer\n");
}
pthread_exit (0);
}
int CalibrateSystem()
{
struct timex ntx;
int ppm;
int status;
//Calibrate Clock system (surely depends also on PLL PPM
// =====================================================
ntx.modes = 0; /* only read */
status = ntp_adjtime(&ntx);
double clockppm;
if (status != TIME_OK)
{
printf("Warning: NTP\n");
return 0;
}
clockppm = (double)ntx.freq/(double)(1 << 16);
if(abs(clockppm)<200)
ppm=clockppm;
printf("Clock PPM = %d\n",ppm);
return ppm;
}
void print_usage()
{
fprintf(stderr,\
"\nrpidatv -%s\n\
Usage:\nrpidatv -i File Input -s Symbolrate -c Fec [-o OutputMode] [-f frequency output] [-l] [-p Power] [-h] \n\
-i path to Transport File Input \n\
-s SymbolRate in KS (125-4000) \n\
-c Fec : 1/2 or 3/4 or 5/6 or 7/8 \n\
-m OutputMode\n\
{RF(Modulate QSK in RF need -f option to set frequency)}\n\
{IQ(Output QPSK I/Q}\n\
{PARALLEL(Output parallel (DTX1,MINIMOD..)}\n\
{IQWITHCLK(Output I/Q with CLK (F5LGJ)}\n\
{DIGITHIN (Output I/Q for Digithin)}\n\
-f Frequency to output in RF Mode in MHZ\n\
-l loop file input\n\
-p Power on output 1..7\n\
-x GPIO Pin output for I or RF {12,18,40}\n\
-y GPIO Pin output for Q {13,19,41,45}\n\
-h help (print this help).\n\
Example : sudo ./rpidatv -i sample.ts -s 250 -c 1/2 -o RF -f 437.5 -l\n\
\n",\
PROGRAM_VERSION);
} /* end function print_usage */
int
main(int argc, char **argv)
{
int i;
//char pagemap_fn[64];
//unsigned char *data;
int OutputPower=5;
int ModeIQ=0;
int DigithinMode=0; //1 allow Clock output + SerialOutput
//int ModeDTX1=0;
my_circular_buffer.buffer=malloc(BIG_BUFFER_SIZE);
my_circular_buffer.head=0;
my_circular_buffer.tail=0;
fprintf(stdout,"RPIDATV Version %s (F5OEO Evariste) on ",__DATE__);
// Nearly there.. open the .ts file specified on the cmdline
fdts = 0;
int a;
int anyargs = 0;
while(1)
{
a = getopt(argc, argv, "i:s:c:hlf:m:p:x:y:");
if(a == -1)
{
if(anyargs) break;
else a='h'; //print usage and exit
}
anyargs = 1;
switch(a)
{
case 'i': // InputFile
FileName=optarg;
fdts = open(FileName, 'r');
break;
case 's': // SymbolRate
SymbolRate = atoi(optarg);
break;
case 'c': // FEC
if(strcmp("1/2",optarg)==0) FEC=1;
if(strcmp("2/3",optarg)==0) FEC=2;
if(strcmp("3/4",optarg)==0) FEC=3;
if(strcmp("5/6",optarg)==0) FEC=5;
if(strcmp("7/8",optarg)==0) FEC=7;
if(strcmp("carrier",optarg)==0) {printf("Rpidatv:Carrier mode\n");FEC=0;}//CARRIER MODE
if(strcmp("test",optarg)==0) FEC=-1;//TEST MODE
break;
case 'h': // help
print_usage();
terminate(0);
break;
case 'l': // loop mode
Loop = 1;
break;
case 'f': // Frequency (Mode RF)
TuneFrequency = atof(optarg)*1000000;
break;
case 'm': // Output mode
if(strcmp("IQ",optarg)==0) ModeIQ=1;
if(strcmp("RF",optarg)==0) ModeIQ=0;;
if(strcmp("PARALLEL",optarg)==0) ModeIQ=2;
if(strcmp("IQWITHCLK",optarg)==0) ModeIQ=1;
if(strcmp("DIGITHIN",optarg)==0) {ModeIQ=1;DigithinMode=1;};
break;
case 'p': // Power
OutputPower= atoi(optarg);
break;
case 'x': // Pin mapping GPIO I or RF
PinOutput[0]=atoi(optarg);
break;
case 'y': // Pin mapping GPIO Q
PinOutput[1]=atoi(optarg);
break;
case -1:
break;
case '?':
if (isprint(optopt) )
{
fprintf(stderr, "rpidatv: unknown option `-%c'.\n", optopt);
}
else
{
fprintf(stderr, "rpidatv: unknown option character `\\x%x'.\n", optopt);
}
print_usage();
exit(1);
break;
default:
print_usage();
exit(1);
break;
}/* end switch a */
}/* end while getopt() */
/* SEARCH FOR NEAR FREQUENCY */
//data=malloc(DATA_FILE_SIZE);
//CalibrateSystem();
dvbsenco_init() ;
if(abs(FEC)>0)
viterbi_init(abs(FEC));
else
viterbi_init(1);
//setSchedPriority(SCHED_PRIORITY); //Seems to help a lot ---------> REMOVED SINCE MEMORY BUFFERING
// Calculate the frequency control word
// The fractional part is stored in the lower 12 bits
//freq_ctl = ((float)(PLLFREQ / CARRIERFREQ)) * ( 1 << 12 );
InitGpio();
InitDma(terminate);
if(ModeIQ==0)
InitUgly();
if(ModeIQ==1)
InitIQ(DigithinMode);
if(ModeIQ==2)
InitDTX1();
usleep(500);
//REMOVE TO TEST
pad_gpios_reg[PADS_GPIO_0] = 0x5a000000 + (OutputPower&0x7) + (1<<4) + (0<<3); // Set output power for I/Q GPIO18/GPIO19
//int NbStep;
// Initialise the DMA
dma_reg[DMA_CS+DMA_CHANNEL*0x40] = BCM2708_DMA_RESET;
udelay(1000);
dma_reg[DMA_CS+DMA_CHANNEL*0x40] = BCM2708_DMA_INT | BCM2708_DMA_END;
udelay(1000);
dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40] = mem_virt_to_phys(ctl->cb);
//printf("DMA CONBLOCK : Virt %x-> Phys %x\n",ctl->cb,mem_virt_to_phys(ctl->cb));
// LET'S START DMA
udelay(100);
dma_reg[DMA_DEBUG+DMA_CHANNEL*0x40] = 7; // clear debug error flags
udelay(100);
// START DMA
//dma_reg[DMA_CS+DMA_CHANNEL*0x40] = 0x10880001; // go, mid priority, wait for outstanding writes :7 Seems Max Priority
udelay(200);
uint32_t last_cb = (uint32_t)ctl->cb;
uint32_t NbSymbol = 0;
//terminate(0); // Before going to DMA
//int PosInByte=0;
// 4000 samples * (32/2IQ) / SR/2 (half full) -> 4000*16/1E6Hz= 64 ms
int TimeToSleep=((8000)*1000)/SymbolRate;
//printf("TimeToSleep = %d\n",TimeToSleep);
//TRY REMOVING DELAY
//printf("Removing Delay");
static volatile uint32_t cur_cb;
int last_sample;
int this_sample;
int free_slots;
//int SumDelay=0;
if(Loop==1) printf("(looping)\n"); else printf("\n");
printf("TS Bitrate should be %lu bit/s\n",(uint32_t)SymbolRate*1000*2*188*abs((long)FEC)/(204L*(abs(FEC)+1L)));
long int start_time;
static long time_difference=0;
struct timespec gettime_now;
// CALIBRATION *************
//#define CALIBRATION 1
#ifdef CALIBRATION
int DiffCB;
dma_reg[DMA_CS+DMA_CHANNEL*0x40] = 0x10880001;
for(i=0;i<30;i++)
{
volatile uint32_t phys_cur_cb,phys_cur_cb2;
int try;
//for(try=0;try<10;try++) {if((phys_cur_cb=dma_reg[DMA_CONBLK_AD])==0) break;usleep(100);}
phys_cur_cb=dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40];
cur_cb = mem_phys_to_virt(phys_cur_cb);
clock_gettime(CLOCK_REALTIME, &gettime_now);
start_time = gettime_now.tv_nsec;
usleep(10000);
phys_cur_cb2=dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40];
DiffCB = mem_phys_to_virt(phys_cur_cb2)-cur_cb;
clock_gettime(CLOCK_REALTIME, &gettime_now);
time_difference = gettime_now.tv_nsec - start_time;
printf("cb_phys =%lx cb_phy2=%lx :Diff %lx \n",phys_cur_cb,phys_cur_cb2,abs(phys_cur_cb2-phys_cur_cb));
DiffCB=abs(phys_cur_cb-phys_cur_cb2);
if(ModeIQ==0)
printf("Calibrate NbCB=%d Time=%d : %f\n",DiffCB/(sizeof(dma_cb_t) * 2),time_difference,1000000.0*DiffCB/(sizeof(dma_cb_t) * 2)/(float)time_difference);
else
printf("Calibrate NbCB=%d Time=%d : %f\n",DiffCB/(sizeof(dma_cb_t) ),time_difference,1000000.0*16*DiffCB/(sizeof(dma_cb_t) )/(float)time_difference);
}
#endif
uchar PacketNULL[BURST_MEM_SIZE];
int k;
for(k=0;k<BURST_MEM_SIZE/188;k++)
{
PacketNULL[0+k*188]=0x47;
PacketNULL[1+k*188]=0x00;
for(i=2;i<188;i++) PacketNULL[i+k*188]=0xFF;
}
if(ModeIQ==0) //UGLY
{
cur_cb = (uint32_t)virtbase;
last_cb=(uint32_t)virtbase + 2*204*8* /*NUM_SAMPLES/8* */ sizeof(dma_cb_t) *2 ;//AGAIN *2 TO AVOID ISSUE ?
}
if(ModeIQ==1)
{
cur_cb = (uint32_t)virtbase;
last_cb=(uint32_t)virtbase + 204*8*2*sizeof(dma_cb_t) ;//*2 Should be "paire" else not aligned to I/Q
}
if(ModeIQ==2)
{
cur_cb = (uint32_t)virtbase;
last_cb=(uint32_t)virtbase + 4*188*8*sizeof(dma_cb_t)*2 ;//*2 Should be "paire" else not aligned to I/Q
}
dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]=mem_virt_to_phys(virtbase);
// Pour que Freeslot<0 au 1er coup
//dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40] = mem_virt_to_phys(virtbase);
unsigned char Init=1;
//unsigned char Resync=0;
//unsigned char Start=1;
clock_gettime(CLOCK_REALTIME, &gettime_now);
printf("%ld:%ld : Fulling buffer \n",gettime_now.tv_sec,gettime_now.tv_nsec);
static uint32_t MaxToGetBuffer=0; // Time of the circular buffer : depend on SIZE and SymbolRate
uint64_t TSRate=SymbolRate*FEC*188*1000.0/(4*204*(FEC+1L));
if(ModeIQ==0)
MaxToGetBuffer=((NUM_SAMPLES-(204*2*4))*1000)/(SymbolRate*2); // ONLY UGLY
if(ModeIQ==1)
MaxToGetBuffer=((NUM_SAMPLES-(204*2*4))*1000*16*2)/(SymbolRate*2);//
if(ModeIQ==2)
{
MaxToGetBuffer=((NUM_SAMPLES-(188*8*4))*1000)/(TSRate);//
}
#ifdef WITH_MEMORY_BUFFER
// ------------------- START THE BUFFER FILLING THREAD ---------------
{
//uint64_t TSRate=SymbolRate*FEC*188*1000.0/(4*204*(FEC+1L));
pthread_attr_t attr;
pthread_mutex_init (&my_circular_buffer.lock, NULL);
printf("TSrate in byte =%llu\n",TSRate);
pthread_attr_init (&attr);
//pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
//pthread_create (&th1,&attr, &FillBigBuffer,NULL);
pthread_create (&th1,NULL, &FillBigBuffer,NULL);
pthread_attr_destroy (&attr);
if(FEC>0)
{
while(BufferAvailable()<(BIG_BUFFER_SIZE*5/10)) // 1/10 SECOND BUFFERING DEPEND ON SYMBOLRATE OR 80% BUFFERSIZE
{
//printf("Init Filling Memory buffer %d\n",BufferAvailable());
//printf(".");
usleep(10000);
}
}
/*
int NbByteInitRead=0;
pthread_mutex_lock(&my_circular_buffer.lock);
while((BufferAvailable()>TSRate)&&(NbByteInitRead%188!=0))
{
read_from_buffer();
NbByteInitRead++;
}
pthread_mutex_unlock(&my_circular_buffer.lock);
*/
printf("End Init Filling Memory buffer %d\n",BufferAvailable());
}
#endif
// -----------------------------------------------------------------
for (;;)
{
//********************************* MODE UGLY **************************************
if(ModeIQ==0)
{
static int StatusCompteur=0;
cur_cb = mem_phys_to_virt(dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]);
this_sample = (cur_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) * 2);
last_sample = (last_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) * 2);
free_slots = this_sample - last_sample;
if (free_slots < 0) // WARNING : ORIGINAL CODE WAS < strictly
{
free_slots += NUM_SAMPLES;
}
else
{
//if(ctl->OverflowControl[0]==ctl->OverflowStatus[1])
{
//printf("Cptoverflow = %d %d \n",ctl->OverflowControl[0],ctl->OverflowStatus[0]);
}
}
TimeToSleep=((NUM_SAMPLES-free_slots-204*2*4)*1000)/((float)SymbolRate*2);//-22000; // 22ms de Switch process
//TimeToSleep=15000+KERNEL_GRANULARITY;
//TimeToSleep=25000;
//printf("cur_cb %lx FreeSlots = %d Time to sleep=%d\n",cur_cb,free_slots,TimeToSleep);
//printf("Buffer Available=%d\n",BufferAvailable());
clock_gettime(CLOCK_REALTIME, &gettime_now);
start_time = gettime_now.tv_nsec;
if(Init==0)
{
if(TimeToSleep>=(2200+KERNEL_GRANULARITY)) // 2ms : Time to process File/Canal Coding
{
if(TimeToSleep>=20000) TimeToSleep=20000;
udelay(TimeToSleep-(2200+KERNEL_GRANULARITY));
TimeToSleep=0;
}
else
{
printf("!");
usleep(1000);//20 ms mini !!
if(free_slots>(NUM_SAMPLES*9/10))
printf("Buffer nearly empty...%d/%d\n",free_slots,NUM_SAMPLES);
}
}
static int free_slots_now;
cur_cb = mem_phys_to_virt(dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]);
this_sample = (cur_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) * 2);
last_sample = (last_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) * 2);
free_slots_now = this_sample - last_sample;
if (free_slots_now < 0) // WARNING : ORIGINAL CODE WAS < strictly
free_slots_now += NUM_SAMPLES;
clock_gettime(CLOCK_REALTIME, &gettime_now);
time_difference = gettime_now.tv_nsec - start_time;
if(time_difference<0) time_difference+=1E9;
if(StatusCompteur%100==0)
{
//SetUglyFrequency(TuneFrequency);
//TuneFrequency+=5000.0;
printf("Memavailable %d/%d FreeSlot=%d/%d Bitrate : %f\n",BufferAvailable(),BIG_BUFFER_SIZE,free_slots_now,NUM_SAMPLES,(1000000.0*(free_slots_now-free_slots))/(float)time_difference);
}
StatusCompteur++;
//printf(" DiffTime = %ld FreeSlot=%d Bitrate : %f\n",time_difference,free_slots_now-free_slots,(1000000.0*(free_slots_now-free_slots))/(float)time_difference);
free_slots=free_slots_now;
// FIX IT : Max(freeslot et Numsample/8)
if(((Init==1)&&(free_slots <= 204*2*4 /*NUM_SAMPLES/8*/))||(FEC==0))
{
printf("%ld:%ld : End of Fulling buffer \n",gettime_now.tv_sec,gettime_now.tv_nsec);
dma_reg[DMA_CS+DMA_CHANNEL*0x40] = 0x10880001; // go, mid priority, wait for outstanding writes :7 Seems Max Priority
Init=0;
}
clock_gettime(CLOCK_REALTIME, &gettime_now);
start_time = gettime_now.tv_nsec;
#ifdef WITH_MEMORY_BUFFER
if((Init==0)&&(free_slots > (NUM_SAMPLES*9/10))&&(BufferAvailable()<=188*2))
{
int k;
store_in_buffer_1880(PacketNULL);
printf("Underflow\n");
}
#endif
while (((free_slots>204*2*4)&&(BufferAvailable()>188*2))||(FEC==0)) //204Bytes*2(IQ)*4 paires/octet
{
static uint32_t BuffAligned[256];
static uchar *buff=(uchar *)BuffAligned ;
static uchar *pRS204;
static int NbIQOutput;
static unsigned char BuffIQ[204*2];
static int k=0;
if((abs(FEC)>0)) //NORMAL MODE , 0 : CARRIER MODE
{
if(FEC>0)
{
#ifndef WITH_MEMORY_BUFFER
static int ByteRead=0;
if ((ByteRead=read(fdts,buff,188))!=188) // Read should be around 20us
{
// printf("END OF FILE OR packet is not 188 long %d\n",data_len);
if(Loop==1)
{
close(fdts);
fdts = open(FileName, 'r');
}
else
{
while(ByteRead!=188)
ByteRead+=read(fdts,buff+ByteRead,188-ByteRead);
//printf("End of processing file\n");
//terminate(0);
}
}
#else
read_from_buffer_188(buff);
#endif
}
else
{
buff[0]=0x47;
memset(buff+1,0,187);
}
if(buff[0]!=0x47) printf("SYNC ERROR \n");
// Time to compute is beetween 200 and 1000 us
energy (buff,buff) ;
if(FEC<0)
{
//unsigned char SyncByte=buff[0];
memset(buff+1,0,187);
}
reed (buff) ;
pRS204= interleave(buff) ;
NbIQOutput=viterbi (pRS204,BuffIQ);
}
else // TEST MODE (CARRIER)
{
NbIQOutput=204;
}
for(k=0;k<NbIQOutput;k++)
{
for(i=3;i>=0;i--)
{
if(abs(FEC)>0)
{
if(FEC>0)
{
ctl->sample[last_sample++]=TabIQ[(BuffIQ[k]>>(i*2))&0x3];
}
else
{
if((k<=32)) ctl->sample[last_sample++]=TabIQ[(BuffIQ[k]>>(i*2))&0x3];
else
{
ctl->sample[last_sample++]=TabIQ[i];
}
}
}
else
{
ctl->sample[last_sample++]=TabIQTest[0];
}
if (last_sample == NUM_SAMPLES) last_sample = 0;
NbSymbol++;
}
free_slots -= 4;
}
/*
static int free_slot_process;
cur_cb = mem_phys_to_virt(dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]);
this_sample = (cur_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) * 2);
free_slot_process = this_sample - last_sample;
if (free_slot_process < 0) // WARNING : ORIGINAL CODE WAS < strictly
free_slot_process += NUM_SAMPLES;
if(free_slot_process>10000) printf("FreeSlotP=%d\n",free_slot_process);
*/
}
//printf("Process UNLOCK\n");
clock_gettime(CLOCK_REALTIME, &gettime_now);
time_difference = gettime_now.tv_nsec - start_time;
if(time_difference<0) time_difference+=1E9;
//printf("Time to Process file =%ld ByteRead = %ld BitRateTS= %ld\n",time_difference,TotalByteRead,TotalByteRead*8*1000000L/(time_difference));
if((Init==0)&&(FEC>0)&&(time_difference>MaxToGetBuffer*1000))
{
dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]=mem_virt_to_phys(virtbase);
last_cb=(uint32_t)virtbase + 2*204*8* /*NUM_SAMPLES/8* */ sizeof(dma_cb_t) *2 ;
printf("File to slow !! wait for %ldus\n",(long int)time_difference/1000);
}
else
last_cb = (uint32_t)virtbase + last_sample * sizeof(dma_cb_t) * 2;
}
//********************************* MODE IQ **************************************
if(ModeIQ==1)
{
static int StatusCompteur=0;
cur_cb = mem_phys_to_virt(dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]);
this_sample = (cur_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) );
last_sample = (last_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) );
free_slots = this_sample - last_sample;
if (free_slots < 0) // WARNING : ORIGINAL CODE WAS < strictly
free_slots += NUM_SAMPLES;
TimeToSleep=((NUM_SAMPLES-free_slots-204*2*4)*1000*16)/((float)SymbolRate*2); // 22ms de Switch process
//printf("FreeSlots = %d Time to sleep=%d\n",free_slots,TimeToSleep);
clock_gettime(CLOCK_REALTIME, &gettime_now);
start_time = gettime_now.tv_nsec;
if(Init==0)
{
if(TimeToSleep>=(2000+KERNEL_GRANULARITY)){
if(TimeToSleep>=20000) TimeToSleep=20000; //Digithin should be every 250ms
udelay(TimeToSleep-(2000+KERNEL_GRANULARITY));
}
else
{
printf("!");
usleep(1000);//20 ms mini !!
if(free_slots>(NUM_SAMPLES*9/10))
{
//printf("Buffer nearly empty...%d/%d\n",free_slots,NUM_SAMPLES);
//printf("$");
}
}
}
//printf("FreeSlots = %d Time to sleep=%d\n",free_slots,TimeToSleep);
if(DigithinMode==1)
{
static unsigned long int serial_start_time;
clock_gettime(CLOCK_REALTIME, &gettime_now);
if(Init==1) serial_start_time=gettime_now.tv_nsec;
static long int DiffSerialTime;
DiffSerialTime=gettime_now.tv_nsec-serial_start_time;
if(DiffSerialTime<0) DiffSerialTime+=1E9;
//printf("Time = %lu\n",DiffSerialTime/1000000L);
//if((DiffSerialTime)/1000000L>200) // Every 500 ms
{
if (uart0_filestream != -1)
{
//printf("Serial %s\n",DigithinCommand);
int count = write(uart0_filestream, DigithinCommand,sizeof(DigithinCommand));
//Filestream, bytes to write, number of bytes to write
if (count < 0)
{
printf("UART TX error\n");
}
else
{
//printf("Serial %d\n",count);
}
}
serial_start_time = gettime_now.tv_nsec;
}
}
static int free_slots_now;
cur_cb = mem_phys_to_virt(dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]);
this_sample = (cur_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) );
last_sample = (last_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t));
free_slots_now = this_sample - last_sample;
if (free_slots_now < 0) // WARNING : ORIGINAL CODE WAS < strictly
free_slots_now += NUM_SAMPLES;
clock_gettime(CLOCK_REALTIME, &gettime_now);
time_difference = gettime_now.tv_nsec - start_time;
if(time_difference<0) time_difference+=1E9;
if(StatusCompteur%100==0)
{
//SetUglyFrequency(TuneFrequency);
//TuneFrequency+=5000.0;
printf("Memavailable %d/%d FreeSlot=%d/%d Bitrate : %f\n",BufferAvailable(),BIG_BUFFER_SIZE,free_slots_now,NUM_SAMPLES,(1000000.0*(free_slots_now-free_slots))/(float)time_difference);
}
StatusCompteur++;
//printf("DiffTime = %ld FreeSlot=%ld Bitrate : %f\n",time_difference,free_slots_now-free_slots,(1000000.0*(free_slots_now-free_slots)*16.0)/(float)time_difference);
free_slots=free_slots_now;
if((Init==1)&&(free_slots <= (204*8*2)))
{
printf("%ld:%ld : End of Fulling buffer \n",gettime_now.tv_sec,gettime_now.tv_nsec);
dma_reg[DMA_CS+DMA_CHANNEL*0x40] = 0x10880001; // go, mid priority, wait for outstanding writes :7 Seems Max Priority
Init=0;
sleep(0);
}
//printf("Free Slots = %d\n",free_slots);
//if (time_difference/1000>TimeToSleep*2) printf("Time %d\n",time_difference/1000);
// FEC 1/2 : 204*2*1/2/8(8=4octets de I et 4 octets de Q) : il faut divisible par 8
//FEC 1/2 : il faut 2*204 pour divisble par 8
//FEC 2/3 : 204 OK
//FEC 3/4 : il faut 4*204
//FEC 5/6 : 340 Octets : il faut 2
//FEC 7/8 : 357 8
clock_gettime(CLOCK_REALTIME, &gettime_now);
start_time = gettime_now.tv_nsec;
#ifdef WITH_MEMORY_BUFFER
if((Init==0)&&(free_slots > (NUM_SAMPLES*9/10))&&(BufferAvailable()<=188*8))
{
int k;
store_in_buffer_1880(PacketNULL);
/*while(BufferAvailable()<188*8)
{
//printf("!");
sleep(1000);
}
*/
/*
pthread_mutex_lock(&my_circular_buffer.lock);
for(k=0;k<8*2;k++)
store_in_buffer_1880(PacketNULL);
pthread_mutex_unlock(&my_circular_buffer.lock);
*/
printf("Underflow\n");
}
#endif
#ifdef WITH_MEMORY_BUFFER
while ((free_slots > (204*8*2))&&((BufferAvailable()>=188*8)||(FEC==0))) //204Bytes*2(IQ)/32
#else
while ((free_slots > (204*8*2))||(FEC==0)) //204Bytes*2(IQ)/32
#endif
{
//static uint32_t BuffAligned[256];
//static uchar *buff=(uchar *)BuffAligned ;
static uchar buff[208];
static uchar *pRS204;
static int NbIQOutput=0;
static unsigned char BuffIQ[204*8*2];
static int k=0;
//static int data_len_total;
//data_len_total=0;
NbIQOutput=0;
// Time to compute is beetween 200 and 1000 us
if(abs(FEC)>0) //NORMAL MODE , 0 : CARRIER MODE
{
for(i=0;i<8;i++)
{
if(FEC>0)
{
#ifndef WITH_MEMORY_BUFFER
/*static*/ int ByteRead=0;
if ((ByteRead=read(fdts,buff,188))!=188) // Read should be around 20us
{
printf("END OF FILE OR packet is not 188 long %d\n",ByteRead);
if(Loop==1)
{
close(fdts);
fdts = open(FileName, 'r');
ByteRead=read(fdts,buff,188);
}
else
{
while(ByteRead!=188)
{
ByteRead+=read(fdts,buff+ByteRead,188-ByteRead);
usleep(1000);
}
printf("ok 188\n");
//terminate(0);
}
}
#else
int ii;
read_from_buffer_188(buff);
#endif
}
else
{
buff[0]=0x47;
memset(buff+1,0,187);
}
if(buff[0]!=0x47) printf("SYNC 188 ERROR \n");
energy (buff,buff) ;
if(FEC<0)
{
memset(buff+1,0x183,187);
//memset(pRS204+1,0,203);
}
reed (buff) ;
pRS204= interleave(buff) ;
//pRS204 = dvbsenco (buff) ;
NbIQOutput+=viterbi (pRS204,BuffIQ+NbIQOutput);
//printf("NbIQ=%d\n",NbIQOutput);
if((NbIQOutput%8)==0) break;
}
}
else
{
//printf("408\n");
NbIQOutput=408;
}
//printf("NbIQoutput=%d %d\n",NbIQOutput,free_slots);
if((NbIQOutput%8)!=0) printf("ERROR ALIGNED \n");
for(k=0;k<NbIQOutput;k+=8)
{
static uint32_t I32,Q32;
I32=0L;
Q32=0L;
for (i=0;i<4;i++)
{
I32|=((BuffIQ[k]&(1<<(i*2+1)))>>(i*2+1))<<(28+i);
I32|=((BuffIQ[k+1]&(1<<(i*2+1)))>>(i*2+1))<<(24+i);
I32|=((BuffIQ[k+2]&(1<<(i*2+1)))>>(i*2+1))<<(20+i);
I32|=((BuffIQ[k+3]&(1<<(i*2+1)))>>(i*2+1))<<(16+i);
I32|=((BuffIQ[k+4]&(1<<(i*2+1)))>>(i*2+1))<<(12+i);
I32|=((BuffIQ[k+5]&(1<<(i*2+1)))>>(i*2+1))<<(8+i);
I32|=((BuffIQ[k+6]&(1<<(i*2+1)))>>(i*2+1))<<(4+i);
I32|=((BuffIQ[k+7]&(1<<(i*2+1)))>>(i*2+1))<<i;
Q32|=((BuffIQ[k]&(1<<(i*2)))>>(i*2))<<(28+i);
Q32|=((BuffIQ[k+1]&(1<<(i*2)))>>(i*2))<<(24+i);
Q32|=((BuffIQ[k+2]&(1<<(i*2)))>>(i*2))<<(20+i);
Q32|=((BuffIQ[k+3]&(1<<(i*2)))>>(i*2))<<(16+i);
Q32|=((BuffIQ[k+4]&(1<<(i*2)))>>(i*2))<<(12+i);
Q32|=((BuffIQ[k+5]&(1<<(i*2)))>>(i*2))<<(8+i);
Q32|=((BuffIQ[k+6]&(1<<(i*2)))>>(i*2))<<(4+i);
Q32|=((BuffIQ[k+7]&(1<<(i*2)))>>(i*2))<<i;
}
if(FEC==0) //CARRIER MODE : OVERWRITE IQ previously calculated
{
//I32=TabIQTestI[NbSymbol%4];
//Q32=TabIQTestQ[NbSymbol%4];
I32=0x55555555;
Q32=0x55555555;
}
/*
if(FEC<0)
{
if(k%204!=0)
{
I32=TabIQTestI[0];
Q32=TabIQTestQ[0];
}
}
*/
ctl->sample[last_sample++] =I32;
if (last_sample == NUM_SAMPLES) last_sample = 0;
ctl->sample[last_sample++] =Q32;
if (last_sample == NUM_SAMPLES) last_sample = 0;
//printf("I32 %x Q32 %x \n",I32,Q32);
NbSymbol++;
free_slots -= 2;
}
}
clock_gettime(CLOCK_REALTIME, &gettime_now);
time_difference = gettime_now.tv_nsec - start_time;
if(time_difference<0) time_difference+=1E9;
if((FEC>0)&&(time_difference>MaxToGetBuffer*1000))
{
printf("File to slow !! wait for %ld us/ %ld us\n",(long int)time_difference/1000,(long int)MaxToGetBuffer);
}
last_cb = (uint32_t)virtbase + last_sample * sizeof(dma_cb_t) ;
}
// ************************************************ MODE DTX 1 ***********************************************
if(ModeIQ==2)
{
//uint32_t static TSRate;
//TSRate=SymbolRate*FEC*188/(4*204*(FEC+1L));
cur_cb = mem_phys_to_virt(dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]);
this_sample = (cur_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t)*2 );
last_sample = (last_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t)*2 );
free_slots = this_sample - last_sample;
if (free_slots < 0) // WARNING : ORIGINAL CODE WAS < strictly
free_slots += NUM_SAMPLES;
//TimeToSleep=((NUM_SAMPLES-free_slots-188*4*2)*800)/((float)TSRate); // 22ms de Switch process
TimeToSleep=2000+KERNEL_GRANULARITY;
//printf("FreeSlots = %d Time to sleep=%d\n",free_slots,TimeToSleep);
clock_gettime(CLOCK_REALTIME, &gettime_now);
start_time = gettime_now.tv_nsec;
if(TimeToSleep>=(2000+KERNEL_GRANULARITY))
{
if(TimeToSleep>=200000) TimeToSleep=200000; //Digithin should be every 250ms
udelay(TimeToSleep-(2000+KERNEL_GRANULARITY));
}
else
{
//usleep(0);//20 ms mini !!
if(free_slots>(NUM_SAMPLES*9/10))
printf("Buffer nearly empty...%d/%d\n",free_slots,NUM_SAMPLES);
}
//printf("FreeSlots = %d Time to sleep=%d\n",free_slots,TimeToSleep);
static int free_slots_now;
cur_cb = mem_phys_to_virt(dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]);
this_sample = (cur_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t)*2);
last_sample = (last_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t)*2);
//printf("%lx %lx\n",this_sample,last_sample);
free_slots_now = this_sample - last_sample;
if (free_slots_now < 0) // WARNING : ORIGINAL CODE WAS < strictly
free_slots_now += NUM_SAMPLES;
clock_gettime(CLOCK_REALTIME, &gettime_now);
time_difference = gettime_now.tv_nsec - start_time;
if(time_difference<0) time_difference+=1E9;
//printf("DiffTime = %ld FreeSlot=%ld Bitrate : %f\n",time_difference,free_slots_now-free_slots,(1000000.0*(free_slots_now-free_slots))/(float)time_difference*2.0);
free_slots=free_slots_now;
if((Init==1)&&(free_slots <= (188*8*4)/*NUM_SAMPLES/8*/))
{
printf("%ld:%ld : End of Fulling buffer \n",gettime_now.tv_sec,gettime_now.tv_nsec);
dma_reg[DMA_CS+DMA_CHANNEL*0x40] = 0x10880001; // go, mid priority, wait for outstanding writes :7 Seems Max Priority
Init=0;
sleep(0);
}
clock_gettime(CLOCK_REALTIME, &gettime_now);
start_time = gettime_now.tv_nsec;
while ((free_slots > (188*8*4))&&(BufferAvailable()>188*8)) //
{
//static uint32_t BuffAligned[256];
//static uchar *buff=(uchar *)BuffAligned ;
static uchar buff[208];
//static int data_len_total;
//data_len_total=0;
for(i=0;i<8;i++)
{
if(FEC>0)
{
/*
static int ByteRead=0;
if ((ByteRead=read(fdts,buff,188))!=188) // Read should be around 20us
{
printf("END OF FILE OR packet is not 188 long %d\n",data_len);
if(Loop==1)
{
close(fdts);
fdts = open(argv[1], 'r');
}
else
{
while(ByteRead!=188)
ByteRead+=read(fdts,buff+ByteRead,188-ByteRead);
//printf("End of processing file\n");
//terminate(0);
}
}
*/
int ii;
pthread_mutex_lock(&my_circular_buffer.lock);
for(ii=0;ii<188;ii++) buff[ii]=read_from_buffer();
pthread_mutex_unlock(&my_circular_buffer.lock);
}
else
{
buff[0]=0x47;
memset(buff+1,0,187);
}
static char MapBit[8]={2,3,4,14,15,17,18,27};
if(buff[0]!=0x47) printf("SYNC 188 ERROR \n");
int BytePacket=0;
volatile uint32_t ByteClear;
volatile uint32_t ByteSet;
int bit;
for(BytePacket=0;BytePacket<188;BytePacket++)
{
ByteSet=0;
ByteClear=(1<<22); //CLK LOW
if((BytePacket==0))
{
ByteSet|= (1 << 24); //TPCLK HIGH
}
else
{
ByteClear|=(1 <<24); //TPCLK 0
}
//TEST
/*if(BytePacket==0)
buff[BytePacket]=0x47;
else buff[BytePacket]=0x12;*/
for(bit=0;bit<8;bit++)
{
ByteSet|=((buff[BytePacket]>>bit)&1)<<MapBit[bit];
ByteClear|=(~((buff[BytePacket]>>bit))&1)<<MapBit[bit];
}
//printf("CYCLE 1:Byte %lx ByteSet %lx ByteClear %lx \n",buff[BytePacket],ByteSet,ByteClear);
ctl->sample[last_sample++] =ByteClear;
if (last_sample == NUM_SAMPLES) last_sample = 0;
ctl->sample[last_sample++] =ByteSet;
if (last_sample == NUM_SAMPLES) last_sample = 0;
//ByteSet=(1<<22);//CLK HIGH
ByteSet=(1<<22);//CLK HIGH
ByteClear=0;//(1<<22);
//printf("CYCLE 2:Byte %lx ByteSet %lx ByteClear %lx \n",buff[BytePacket],ByteSet,ByteClear);
ctl->sample[last_sample++] =ByteClear;
if (last_sample == NUM_SAMPLES) last_sample = 0;
ctl->sample[last_sample++] =ByteSet;
if (last_sample == NUM_SAMPLES) last_sample = 0;
free_slots -= 4; // *2 porbleme de Index entre CBP ET DATA
}
}
}
clock_gettime(CLOCK_REALTIME, &gettime_now);
time_difference = gettime_now.tv_nsec - start_time;
if(time_difference<0) time_difference+=1E9;
if((FEC>0)&&(time_difference>MaxToGetBuffer*4000))
{
printf("File to slow !! wait for %ld us/ %ld us\n",(long int)time_difference/1000,(long int)MaxToGetBuffer);
}
last_cb = (uint32_t)virtbase + last_sample * sizeof(dma_cb_t)*2 ;
}
}
terminate(0);
return(0);
}