diff --git a/src/gpio.cpp b/src/gpio.cpp index f898b4d..4acc606 100644 --- a/src/gpio.cpp +++ b/src/gpio.cpp @@ -15,9 +15,7 @@ This program is free software: you can redistribute it and/or modify along with this program. If not, see . */ - -extern "C" -{ +extern "C" { #include "mailbox.h" } #include "gpio.h" @@ -29,311 +27,317 @@ extern "C" gpio::gpio(uint32_t base, uint32_t len) { - - gpioreg=( uint32_t *)mapmem(base,len); + gpioreg = (uint32_t *)mapmem(base, len); } - uint32_t gpio::GetPeripheralBase() { RASPBERRY_PI_INFO_T info; - uint32_t BCM2708_PERI_BASE=0; - if (getRaspberryPiInformation(&info) > 0) + uint32_t BCM2708_PERI_BASE = 0; + if (getRaspberryPiInformation(&info) > 0) { - if(info.peripheralBase==RPI_BROADCOM_2835_PERIPHERAL_BASE) + if (info.peripheralBase == RPI_BROADCOM_2835_PERIPHERAL_BASE) { - BCM2708_PERI_BASE = info.peripheralBase ; + BCM2708_PERI_BASE = info.peripheralBase; } - if((info.peripheralBase==RPI_BROADCOM_2836_PERIPHERAL_BASE)||(info.peripheralBase==RPI_BROADCOM_2837_PERIPHERAL_BASE)) + if ((info.peripheralBase == RPI_BROADCOM_2836_PERIPHERAL_BASE) || (info.peripheralBase == RPI_BROADCOM_2837_PERIPHERAL_BASE)) { - BCM2708_PERI_BASE = info.peripheralBase ; + BCM2708_PERI_BASE = info.peripheralBase; } } return BCM2708_PERI_BASE; } - //******************** DMA Registers *************************************** -dmagpio::dmagpio():gpio(GetPeripheralBase()+DMA_BASE,DMA_LEN) +dmagpio::dmagpio() : gpio(GetPeripheralBase() + DMA_BASE, DMA_LEN) { } // ***************** CLK Registers ***************************************** -clkgpio::clkgpio():gpio(GetPeripheralBase()+CLK_BASE,CLK_LEN) +clkgpio::clkgpio() : gpio(GetPeripheralBase() + CLK_BASE, CLK_LEN) { SetppmFromNTP(); } clkgpio::~clkgpio() { - gpioreg[GPCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber|(0 << 4) ; //4 is START CLK - + gpioreg[GPCLK_CNTL] = 0x5A000000 | (Mash << 9) | pllnumber | (0 << 4); //4 is START CLK + usleep(100); } -int clkgpio::SetPllNumber(int PllNo,int MashType) +int clkgpio::SetPllNumber(int PllNo, int MashType) { //print_clock_tree(); - if(PllNo<8) - pllnumber=PllNo; + if (PllNo < 8) + pllnumber = PllNo; else - pllnumber=clk_pllc; - - if(MashType<4) - Mash=MashType; + pllnumber = clk_pllc; + + if (MashType < 4) + Mash = MashType; else - Mash=0; - gpioreg[GPCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber/*|(1 << 5)*/ ; //5 is Reset CLK + Mash = 0; + gpioreg[GPCLK_CNTL] = 0x5A000000 | (Mash << 9) | pllnumber /*|(1 << 5)*/; //5 is Reset CLK usleep(100); - Pllfrequency=GetPllFrequency(pllnumber); + Pllfrequency = GetPllFrequency(pllnumber); return 0; } uint64_t clkgpio::GetPllFrequency(int PllNo) { - uint64_t Freq=0; - switch(PllNo) + uint64_t Freq = 0; + switch (PllNo) { - case clk_osc: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);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);break; - case clk_plld:Freq=(XOSC_FREQUENCY*((uint64_t)gpioreg[PLLD_CTRL]&0x3ff) +(XOSC_FREQUENCY*(uint64_t)gpioreg[PLLD_FRAC])/(1<<20))/(gpioreg[PLLD_PER]>>1);break; - case clk_hdmi:Freq=XOSC_FREQUENCY*((uint64_t)gpioreg[PLLH_CTRL]&0x3ff) +XOSC_FREQUENCY*(uint64_t)gpioreg[PLLH_FRAC]/(1<<20);break; + case clk_osc: + 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); + 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); + break; + case clk_plld: + Freq = (XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLD_CTRL] & 0x3ff) + (XOSC_FREQUENCY * (uint64_t)gpioreg[PLLD_FRAC]) / (1 << 20)) / (gpioreg[PLLD_PER] >> 1); + break; + case clk_hdmi: + Freq = XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLH_CTRL] & 0x3ff) + XOSC_FREQUENCY * (uint64_t)gpioreg[PLLH_FRAC] / (1 << 20); + break; } - fprintf(stderr,"Freq = %lld\n",Freq); + fprintf(stderr, "Freq = %lld\n", Freq); return Freq; } - -int clkgpio::SetClkDivFrac(uint32_t Div,uint32_t Frac) +int clkgpio::SetClkDivFrac(uint32_t Div, uint32_t Frac) { - - gpioreg[GPCLK_DIV] = 0x5A000000 | ((Div)<<12) | Frac; + + gpioreg[GPCLK_DIV] = 0x5A000000 | ((Div) << 12) | Frac; usleep(100); - fprintf(stderr,"Clk Number %d div %d frac %d\n",pllnumber,Div,Frac); + fprintf(stderr, "Clk Number %d div %d frac %d\n", pllnumber, Div, Frac); //gpioreg[GPCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber |(1<<4) ; //4 is START CLK // usleep(10); return 0; - } -int clkgpio::SetMasterMultFrac(uint32_t Mult,uint32_t Frac) +int clkgpio::SetMasterMultFrac(uint32_t Mult, uint32_t Frac) { - - //fprintf(stderr,"Master Mult %d Frac %d\n",Mult,Frac); - gpioreg[PLLA_CTRL] = (0x5a<<24) | (0x21<<12) | Mult; - usleep(100); - gpioreg[PLLA_FRAC]= 0x5A000000 | Frac ; - - return 0; + //fprintf(stderr,"Master Mult %d Frac %d\n",Mult,Frac); + gpioreg[PLLA_CTRL] = (0x5a << 24) | (0x21 << 12) | Mult; //PDIV=1 + usleep(100); + gpioreg[PLLA_FRAC] = 0x5A000000 | Frac; + + return 0; } int clkgpio::SetFrequency(double Frequency) { - if(ModulateFromMasterPLL) + if (ModulateFromMasterPLL) { - double FloatMult=((double)(CentralFrequency+Frequency)*PllFixDivider)/((double)(XOSC_FREQUENCY)*(1-clk_ppm*1e-6)); // -ppm : compensate ppm - 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 - uint32_t FracMultiply=freqctl&0xFFFFF; + double FloatMult = ((double)(CentralFrequency + Frequency) * PllFixDivider) / ((double)(XOSC_FREQUENCY) * (1 - clk_ppm * 1e-6)); // -ppm : compensate ppm + 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 + uint32_t FracMultiply = freqctl & 0xFFFFF; //gpioreg[PLLA_FRAC]= 0x5A000000 | FracMultiply ; // Only Frac is Sent - SetMasterMultFrac(IntMultiply,FracMultiply); - + SetMasterMultFrac(IntMultiply, FracMultiply); } else { - double Freqresult=(double)Pllfrequency/(double)(CentralFrequency+Frequency); - uint32_t FreqDivider=(uint32_t)Freqresult; - uint32_t FreqFractionnal=(uint32_t) (4096*(Freqresult-(double)FreqDivider)); - if((FreqDivider>4096)||(FreqDivider<2)) fprintf(stderr,"Frequency out of range\n"); - printf("DIV/FRAC %u/%u \n",FreqDivider,FreqFractionnal); - - SetClkDivFrac(FreqDivider,FreqFractionnal); + double Freqresult = (double)Pllfrequency / (double)(CentralFrequency + Frequency); + uint32_t FreqDivider = (uint32_t)Freqresult; + uint32_t FreqFractionnal = (uint32_t)(4096 * (Freqresult - (double)FreqDivider)); + if ((FreqDivider > 4096) || (FreqDivider < 2)) + fprintf(stderr, "Frequency out of range\n"); + printf("DIV/FRAC %u/%u \n", FreqDivider, FreqFractionnal); + + SetClkDivFrac(FreqDivider, FreqFractionnal); } - + return 0; - } - uint32_t clkgpio::GetMasterFrac(double Frequency) { - if(ModulateFromMasterPLL) + if (ModulateFromMasterPLL) { - double 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 - uint32_t FracMultiply=freqctl&0xFFFFF; + double 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 + uint32_t FracMultiply = freqctl & 0xFFFFF; return FracMultiply; } else return 0; //Not in Master CLk mode - } -int clkgpio::ComputeBestLO(uint64_t Frequency,int Bandwidth) -{ +int clkgpio::ComputeBestLO(uint64_t Frequency, int Bandwidth) +{ // Algorithm adapted from https://github.com/SaucySoliton/PiFmRds/blob/master/src/pi_fm_rds.c // Choose an integer divider for GPCLK0 - // - // There may be improvements possible to this algorithm. - double xtal_freq_recip=1.0/19.2e6; // todo PPM correction - int best_divider=0; + // + // There may be improvements possible to this algorithm. + double xtal_freq_recip = 1.0 / 19.2e6; // todo PPM correction + int best_divider = 0; - - int solution_count=0; - //printf("carrier:%3.2f ",carrier_freq/1e6); - int divider,min_int_multiplier,max_int_multiplier, fom, int_multiplier, best_fom=0; - double frac_multiplier; - best_divider=0; - for( divider=1;divider<4096;divider++) - { - if( Frequency*divider < 600e6 ) continue; // widest accepted frequency range - if( Frequency*divider > 1500e6 ) break; + int solution_count = 0; + //printf("carrier:%3.2f ",carrier_freq/1e6); + int divider, min_int_multiplier, max_int_multiplier, fom, int_multiplier, best_fom = 0; + double frac_multiplier; + best_divider = 0; + for (divider = 1; divider < 4096; divider++)//1 is allowed only for MASH=0 + { + if (Frequency * divider < 600e6) + continue; // widest accepted frequency range + if (Frequency * divider > 1700e6) // By Experiment on Rpi3B + break; - max_int_multiplier=((int)((double)(Frequency+Bandwidth)*divider*xtal_freq_recip)); - min_int_multiplier=((int)((double)(Frequency-Bandwidth)*divider*xtal_freq_recip)); - if( min_int_multiplier!=max_int_multiplier ) continue; // don't cross integer boundary + max_int_multiplier = ((int)((double)(Frequency + Bandwidth) * divider * xtal_freq_recip)); + min_int_multiplier = ((int)((double)(Frequency - Bandwidth) * divider * xtal_freq_recip)); + if (min_int_multiplier != max_int_multiplier) + continue; // don't cross integer boundary - solution_count++; // if we make it here the solution is acceptable, - fom=0; // but we want a good solution + solution_count++; // if we make it here the solution is acceptable, + fom = 0; // but we want a good solution - if( Frequency*divider > 900e6 ) fom++; // prefer freqs closer to 1000 - if( Frequency*divider < 1100e6 ) fom++; - if( Frequency*divider > 800e6 ) fom++; // accepted frequency range - if( Frequency*divider < 1200e6 ) fom++; - + if (Frequency * divider > 900e6) + fom++; // prefer freqs closer to 1000 + if (Frequency * divider < 1100e6) + fom++; + if (Frequency * divider > 800e6) + fom++; // accepted frequency range + if (Frequency * divider < 1200e6) + fom++; - frac_multiplier=((double)(Frequency)*divider*xtal_freq_recip); - int_multiplier = (int) frac_multiplier; - frac_multiplier = frac_multiplier - int_multiplier; - if((int_multiplier%2)==0) fom++; - if( (frac_multiplier>0.4) && (frac_multiplier<0.6) ) fom+=2; // prefer mulipliers away from integer boundaries + frac_multiplier = ((double)(Frequency)*divider * xtal_freq_recip); + int_multiplier = (int)frac_multiplier; + frac_multiplier = frac_multiplier - int_multiplier; + if ((int_multiplier % 2) == 0) + fom++; + if ((frac_multiplier > 0.4) && (frac_multiplier < 0.6)) + fom += 2; // prefer mulipliers away from integer boundaries + //if( divider%2 == 1 ) fom+=2; // prefer odd dividers + // Even and odd dividers could have different harmonic content, + // but the latest measurements have shown no significant difference. - //if( divider%2 == 1 ) fom+=2; // prefer odd dividers - // Even and odd dividers could have different harmonic content, - // but the latest measurements have shown no significant difference. - - - //printf(" multiplier:%f divider:%d VCO: %4.1fMHz\n",carrier_freq*divider*xtal_freq_recip,divider,(double)carrier_freq*divider/1e6); - if( fom > best_fom ) - { - best_fom=fom; - best_divider=divider; - } - } - if(solution_count>0) + printf("Try multiplier:%f divider:%d VCO: %4.1fMHz\n",Frequency*divider*xtal_freq_recip,divider,(double)Frequency*divider/1e6); + if (fom > best_fom) { - PllFixDivider=best_divider; - fprintf(stderr," multiplier:%f divider:%d VCO: %4.1fMHz\n",Frequency*best_divider*xtal_freq_recip,best_divider,(double)Frequency*best_divider/1e6); - return 0; + best_fom = fom; + best_divider = divider; } - else - { - fprintf(stderr,"Central frequency not available !!!!!!\n"); - return -1; - } + } + if (solution_count > 0) + { + PllFixDivider = best_divider; + fprintf(stderr, " multiplier:%f divider:%d VCO: %4.1fMHz\n", Frequency * best_divider * xtal_freq_recip, best_divider, (double)Frequency * best_divider / 1e6); + return 0; + } + else + { + fprintf(stderr, "Central frequency not available !!!!!!\n"); + return -1; + } } double clkgpio::GetFrequencyResolution() { - double res=0; - if(ModulateFromMasterPLL) + double res = 0; + if (ModulateFromMasterPLL) { - res=XOSC_FREQUENCY/(double)(1<<20)/PllFixDivider; + res = XOSC_FREQUENCY / (double)(1 << 20) / PllFixDivider; } else { - double Freqresult=(double)Pllfrequency/(double)(CentralFrequency); - uint32_t FreqDivider=(uint32_t)Freqresult; - res=(Pllfrequency/(double)(FreqDivider+1)-Pllfrequency/(double)(FreqDivider))/4096.0; + double Freqresult = (double)Pllfrequency / (double)(CentralFrequency); + uint32_t FreqDivider = (uint32_t)Freqresult; + res = (Pllfrequency / (double)(FreqDivider + 1) - Pllfrequency / (double)(FreqDivider)) / 4096.0; } return res; } double clkgpio::GetRealFrequency(double Frequency) { - double FloatMult=((double)(CentralFrequency+Frequency)*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 - uint32_t FracMultiply=freqctl&0xFFFFF; - double RealFrequency=((double)IntMultiply+(FracMultiply/(double)(1<<20)))*(double)(XOSC_FREQUENCY)/PllFixDivider-(CentralFrequency+Frequency); - return RealFrequency; + double FloatMult = ((double)(CentralFrequency + Frequency) * 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 + uint32_t FracMultiply = freqctl & 0xFFFFF; + double RealFrequency = ((double)IntMultiply + (FracMultiply / (double)(1 << 20))) * (double)(XOSC_FREQUENCY) / PllFixDivider - (CentralFrequency + Frequency); + return RealFrequency; } -int clkgpio::SetCenterFrequency(uint64_t Frequency,int Bandwidth) +int clkgpio::SetCenterFrequency(uint64_t Frequency, int Bandwidth) { - CentralFrequency=Frequency; - if(ModulateFromMasterPLL) + CentralFrequency = Frequency; + if (ModulateFromMasterPLL) { //Choose best PLLDiv and Div - ComputeBestLO(Frequency,Bandwidth); //FixeDivider update - + ComputeBestLO(Frequency, Bandwidth); //FixeDivider update + SetFrequency(0); usleep(1000); - if((gpioreg[CM_LOCK]&CM_LOCK_FLOCKA)>0) - fprintf(stderr,"Master PLLA Locked\n"); + if ((gpioreg[CM_LOCK] & CM_LOCK_FLOCKA) > 0) + fprintf(stderr, "Master PLLA Locked\n"); else - fprintf(stderr,"Warning ! Master PLLA NOT Locked !!!!\n"); - SetClkDivFrac(PllFixDivider,0); // NO MASH !!!! + fprintf(stderr, "Warning ! Master PLLA NOT Locked !!!!\n"); + SetClkDivFrac(PllFixDivider, 0); // NO MASH !!!! usleep(100); - + usleep(100); - gpioreg[GPCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber|(1 << 4) ; //4 is START CLK + gpioreg[GPCLK_CNTL] = 0x5A000000 | (Mash << 9) | pllnumber | (1 << 4); //4 is START CLK usleep(100); - gpioreg[GPCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber|(1 << 4) ; //4 is START CLK + gpioreg[GPCLK_CNTL] = 0x5A000000 | (Mash << 9) | pllnumber | (1 << 4); //4 is START CLK usleep(100); } else { - GetPllFrequency(pllnumber);// Be sure to get the master PLL frequency - gpioreg[GPCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber|(1 << 4) ; //4 is START CLK + GetPllFrequency(pllnumber); // Be sure to get the master PLL frequency + gpioreg[GPCLK_CNTL] = 0x5A000000 | (Mash << 9) | pllnumber | (1 << 4); //4 is START CLK } - return 0; + return 0; } void clkgpio::SetPhase(bool inversed) { - uint32_t StateBefore=clkgpio::gpioreg[GPCLK_CNTL]; - clkgpio::gpioreg[GPCLK_CNTL]= (0x5A<<24) | StateBefore | ((inversed?1:0)<<8) | 1<<5; - clkgpio::gpioreg[GPCLK_CNTL]= (0x5A<<24) | StateBefore | ((inversed?1:0)<<8) | 0<<5; + uint32_t StateBefore = clkgpio::gpioreg[GPCLK_CNTL]; + clkgpio::gpioreg[GPCLK_CNTL] = (0x5A << 24) | StateBefore | ((inversed ? 1 : 0) << 8) | 1 << 5; + clkgpio::gpioreg[GPCLK_CNTL] = (0x5A << 24) | StateBefore | ((inversed ? 1 : 0) << 8) | 0 << 5; } - +//Should inspect https://github.com/raspberrypi/linux/blob/ffd7bf4085b09447e5db96edd74e524f118ca3fe/drivers/clk/bcm/clk-bcm2835.c#L695 void clkgpio::SetAdvancedPllMode(bool Advanced) { - ModulateFromMasterPLL=Advanced; - if(ModulateFromMasterPLL) + ModulateFromMasterPLL = Advanced; + if (ModulateFromMasterPLL) { - SetPllNumber(clk_plla,0); // Use PPL_A , Do not USE MASH which generates spurious - gpioreg[0x104/4]=0x5A00020A; // Enable Plla_PER + SetPllNumber(clk_plla, 0); // Use PPL_A , Do not USE MASH which generates spurious + gpioreg[0x104 / 4] = 0x5A00022A; // Enable Plla_PER usleep(100); - + uint32_t ana[4]; - for(int i=3;i>=0;i--) + for (int i = 3; i >= 0; i--) { - ana[i]=gpioreg[(0x1010/4)+i]; + ana[i] = gpioreg[(0x1010 / 4) + i]; } - - //ana[1]&=~(1<<14); // No use prediv means Frequency - ana[1]|=(1<<14); // use prediv means Frequency*2 - for(int i=3;i>=0;i--) + + ana[1]&=~(1<<14); // No use prediv means Frequency + //ana[1] |= (1 << 14); // use prediv means Frequency*2 + for (int i = 3; i >= 0; i--) { - gpioreg[(0x1010/4)+i]=(0x5A<<24)|ana[i]; + gpioreg[(0x1010 / 4) + i] = (0x5A << 24) | ana[i]; } - - + usleep(100); - gpioreg[PLLA_PER]=0x5A000002; // Div ? + gpioreg[PLLA_CORE] = 0x5A000001; // Div ? + gpioreg[PLLA_PER] = 0x5A000001; // Div ? usleep(100); } } @@ -341,127 +345,131 @@ void clkgpio::SetAdvancedPllMode(bool Advanced) void clkgpio::print_clock_tree(void) { - printf("PLLC_DIG0=%08x\n",gpioreg[(0x1020/4)]); - printf("PLLC_DIG1=%08x\n",gpioreg[(0x1024/4)]); - printf("PLLC_DIG2=%08x\n",gpioreg[(0x1028/4)]); - printf("PLLC_DIG3=%08x\n",gpioreg[(0x102c/4)]); - printf("PLLC_ANA0=%08x\n",gpioreg[(0x1030/4)]); - printf("PLLC_ANA1=%08x\n",gpioreg[(0x1034/4)]); - printf("PLLC_ANA2=%08x\n",gpioreg[(0x1038/4)]); - printf("PLLC_ANA3=%08x\n",gpioreg[(0x103c/4)]); - printf("PLLC_DIG0R=%08x\n",gpioreg[(0x1820/4)]); - printf("PLLC_DIG1R=%08x\n",gpioreg[(0x1824/4)]); - printf("PLLC_DIG2R=%08x\n",gpioreg[(0x1828/4)]); - printf("PLLC_DIG3R=%08x\n",gpioreg[(0x182c/4)]); + printf("PLLC_DIG0=%08x\n", gpioreg[(0x1020 / 4)]); + printf("PLLC_DIG1=%08x\n", gpioreg[(0x1024 / 4)]); + printf("PLLC_DIG2=%08x\n", gpioreg[(0x1028 / 4)]); + printf("PLLC_DIG3=%08x\n", gpioreg[(0x102c / 4)]); + printf("PLLC_ANA0=%08x\n", gpioreg[(0x1030 / 4)]); + printf("PLLC_ANA1=%08x\n", gpioreg[(0x1034 / 4)]); + printf("PLLC_ANA2=%08x\n", gpioreg[(0x1038 / 4)]); + printf("PLLC_ANA3=%08x\n", gpioreg[(0x103c / 4)]); + printf("PLLC_DIG0R=%08x\n", gpioreg[(0x1820 / 4)]); + printf("PLLC_DIG1R=%08x\n", gpioreg[(0x1824 / 4)]); + printf("PLLC_DIG2R=%08x\n", gpioreg[(0x1828 / 4)]); + printf("PLLC_DIG3R=%08x\n", gpioreg[(0x182c / 4)]); - printf("PLLA_ANA0=%08x\n",gpioreg[(0x1010/4)]); - printf("PLLA_ANA1=%08x prediv=%d\n",gpioreg[(0x1014/4)],(gpioreg[(0x1014/4)]>>14)&1); - printf("PLLA_ANA2=%08x\n",gpioreg[(0x1018/4)]); - printf("PLLA_ANA3=%08x\n",gpioreg[(0x101c/4)]); - - printf("GNRIC CTL=%08x DIV=%8x ",gpioreg[ 0],gpioreg[ 1]); - printf("VPU CTL=%08x DIV=%8x\n",gpioreg[ 2],gpioreg[ 3]); - printf("SYS CTL=%08x DIV=%8x ",gpioreg[ 4],gpioreg[ 5]); - printf("PERIA CTL=%08x DIV=%8x\n",gpioreg[ 6],gpioreg[ 7]); - printf("PERII CTL=%08x DIV=%8x ",gpioreg[ 8],gpioreg[ 9]); - printf("H264 CTL=%08x DIV=%8x\n",gpioreg[10],gpioreg[11]); - printf("ISP CTL=%08x DIV=%8x ",gpioreg[12],gpioreg[13]); - printf("V3D CTL=%08x DIV=%8x\n",gpioreg[14],gpioreg[15]); + printf("PLLA_ANA0=%08x\n", gpioreg[(0x1010 / 4)]); + printf("PLLA_ANA1=%08x prediv=%d\n", gpioreg[(0x1014 / 4)], (gpioreg[(0x1014 / 4)] >> 14) & 1); + printf("PLLA_ANA2=%08x\n", gpioreg[(0x1018 / 4)]); + printf("PLLA_ANA3=%08x\n", gpioreg[(0x101c / 4)]); - printf("CAM0 CTL=%08x DIV=%8x ",gpioreg[16],gpioreg[17]); - printf("CAM1 CTL=%08x DIV=%8x\n",gpioreg[18],gpioreg[19]); - printf("CCP2 CTL=%08x DIV=%8x ",gpioreg[20],gpioreg[21]); - printf("DSI0E CTL=%08x DIV=%8x\n",gpioreg[22],gpioreg[23]); - printf("DSI0P CTL=%08x DIV=%8x ",gpioreg[24],gpioreg[25]); - printf("DPI CTL=%08x DIV=%8x\n",gpioreg[26],gpioreg[27]); - printf("GP0 CTL=%08x DIV=%8x ",gpioreg[0x70/4],gpioreg[0x74/4]); - printf("GP1 CTL=%08x DIV=%8x\n",gpioreg[30],gpioreg[31]); + printf("GNRIC CTL=%08x DIV=%8x ", gpioreg[0], gpioreg[1]); + printf("VPU CTL=%08x DIV=%8x\n", gpioreg[2], gpioreg[3]); + printf("SYS CTL=%08x DIV=%8x ", gpioreg[4], gpioreg[5]); + printf("PERIA CTL=%08x DIV=%8x\n", gpioreg[6], gpioreg[7]); + printf("PERII CTL=%08x DIV=%8x ", gpioreg[8], gpioreg[9]); + printf("H264 CTL=%08x DIV=%8x\n", gpioreg[10], gpioreg[11]); + printf("ISP CTL=%08x DIV=%8x ", gpioreg[12], gpioreg[13]); + printf("V3D CTL=%08x DIV=%8x\n", gpioreg[14], gpioreg[15]); - printf("GP2 CTL=%08x DIV=%8x ",gpioreg[32],gpioreg[33]); - printf("HSM CTL=%08x DIV=%8x\n",gpioreg[34],gpioreg[35]); - printf("OTP CTL=%08x DIV=%8x ",gpioreg[36],gpioreg[37]); - printf("PCM CTL=%08x DIV=%8x\n",gpioreg[38],gpioreg[39]); - printf("PWM CTL=%08x DIV=%8x ",gpioreg[40],gpioreg[41]); - printf("SLIM CTL=%08x DIV=%8x\n",gpioreg[42],gpioreg[43]); - printf("SMI CTL=%08x DIV=%8x ",gpioreg[44],gpioreg[45]); - printf("SMPS CTL=%08x DIV=%8x\n",gpioreg[46],gpioreg[47]); + printf("CAM0 CTL=%08x DIV=%8x ", gpioreg[16], gpioreg[17]); + printf("CAM1 CTL=%08x DIV=%8x\n", gpioreg[18], gpioreg[19]); + printf("CCP2 CTL=%08x DIV=%8x ", gpioreg[20], gpioreg[21]); + printf("DSI0E CTL=%08x DIV=%8x\n", gpioreg[22], gpioreg[23]); + printf("DSI0P CTL=%08x DIV=%8x ", gpioreg[24], gpioreg[25]); + printf("DPI CTL=%08x DIV=%8x\n", gpioreg[26], gpioreg[27]); + printf("GP0 CTL=%08x DIV=%8x ", gpioreg[0x70 / 4], gpioreg[0x74 / 4]); + printf("GP1 CTL=%08x DIV=%8x\n", gpioreg[30], gpioreg[31]); - printf("TCNT CTL=%08x DIV=%8x ",gpioreg[48],gpioreg[49]); - printf("TEC CTL=%08x DIV=%8x\n",gpioreg[50],gpioreg[51]); - printf("TD0 CTL=%08x DIV=%8x ",gpioreg[52],gpioreg[53]); - printf("TD1 CTL=%08x DIV=%8x\n",gpioreg[54],gpioreg[55]); + printf("GP2 CTL=%08x DIV=%8x ", gpioreg[32], gpioreg[33]); + printf("HSM CTL=%08x DIV=%8x\n", gpioreg[34], gpioreg[35]); + printf("OTP CTL=%08x DIV=%8x ", gpioreg[36], gpioreg[37]); + printf("PCM CTL=%08x DIV=%8x\n", gpioreg[38], gpioreg[39]); + printf("PWM CTL=%08x DIV=%8x ", gpioreg[40], gpioreg[41]); + printf("SLIM CTL=%08x DIV=%8x\n", gpioreg[42], gpioreg[43]); + printf("SMI CTL=%08x DIV=%8x ", gpioreg[44], gpioreg[45]); + printf("SMPS CTL=%08x DIV=%8x\n", gpioreg[46], gpioreg[47]); - printf("TSENS CTL=%08x DIV=%8x ",gpioreg[56],gpioreg[57]); - printf("TIMER CTL=%08x DIV=%8x\n",gpioreg[58],gpioreg[59]); - printf("UART CTL=%08x DIV=%8x ",gpioreg[60],gpioreg[61]); - printf("VEC CTL=%08x DIV=%8x\n",gpioreg[62],gpioreg[63]); - + printf("TCNT CTL=%08x DIV=%8x ", gpioreg[48], gpioreg[49]); + printf("TEC CTL=%08x DIV=%8x\n", gpioreg[50], gpioreg[51]); + printf("TD0 CTL=%08x DIV=%8x ", gpioreg[52], gpioreg[53]); + printf("TD1 CTL=%08x DIV=%8x\n", gpioreg[54], gpioreg[55]); - printf("PULSE CTL=%08x DIV=%8x ",gpioreg[100],gpioreg[101]); - printf("PLLT CTL=%08x DIV=????????\n",gpioreg[76]); + printf("TSENS CTL=%08x DIV=%8x ", gpioreg[56], gpioreg[57]); + printf("TIMER CTL=%08x DIV=%8x\n", gpioreg[58], gpioreg[59]); + printf("UART CTL=%08x DIV=%8x ", gpioreg[60], gpioreg[61]); + printf("VEC CTL=%08x DIV=%8x\n", gpioreg[62], gpioreg[63]); - printf("DSI1E CTL=%08x DIV=%8x ",gpioreg[86],gpioreg[87]); - printf("DSI1P CTL=%08x DIV=%8x\n",gpioreg[88],gpioreg[89]); - printf("AVE0 CTL=%08x DIV=%8x\n",gpioreg[90],gpioreg[91]); + printf("PULSE CTL=%08x DIV=%8x ", gpioreg[100], gpioreg[101]); + printf("PLLT CTL=%08x DIV=????????\n", gpioreg[76]); - printf("CMPLLA=%08x ",gpioreg[0x104/4]); - printf("CMPLLC=%08x \n",gpioreg[0x108/4]); - printf("CMPLLD=%08x ",gpioreg[0x10C/4]); - printf("CMPLLH=%08x \n",gpioreg[0x110/4]); - - printf("EMMC CTL=%08x DIV=%8x\n",gpioreg[112],gpioreg[113]); - printf("EMMC CTL=%08x DIV=%8x\n",gpioreg[112],gpioreg[113]); - printf("EMMC CTL=%08x DIV=%8x\n",gpioreg[112],gpioreg[113]); - + printf("DSI1E CTL=%08x DIV=%8x ", gpioreg[86], gpioreg[87]); + printf("DSI1P CTL=%08x DIV=%8x\n", gpioreg[88], gpioreg[89]); + printf("AVE0 CTL=%08x DIV=%8x\n", gpioreg[90], gpioreg[91]); - // Sometimes calculated frequencies are off by a factor of 2 - // ANA1 bit 14 may indicate that a /2 prescaler is active - printf("PLLA PDIV=%d NDIV=%d FRAC=%d ",(gpioreg[PLLA_CTRL]>>16) ,gpioreg[PLLA_CTRL]&0x3ff, gpioreg[PLLA_FRAC] ); - printf(" %f MHz\n",19.2* ((float)(gpioreg[PLLA_CTRL]&0x3ff) + ((float)gpioreg[PLLA_FRAC])/((float)(1<<20))) ); - printf("DSI0=%d CORE=%d PER=%d CCP2=%d\n\n",gpioreg[PLLA_DSI0],gpioreg[PLLA_CORE],gpioreg[PLLA_PER],gpioreg[PLLA_CCP2]); + printf("CMPLLA=%08x ", gpioreg[0x104 / 4]); + printf("CMPLLC=%08x \n", gpioreg[0x108 / 4]); + printf("CMPLLD=%08x ", gpioreg[0x10C / 4]); + printf("CMPLLH=%08x \n", gpioreg[0x110 / 4]); + printf("EMMC CTL=%08x DIV=%8x\n", gpioreg[112], gpioreg[113]); + printf("EMMC CTL=%08x DIV=%8x\n", gpioreg[112], gpioreg[113]); + printf("EMMC CTL=%08x DIV=%8x\n", gpioreg[112], gpioreg[113]); - printf("PLLB PDIV=%d NDIV=%d FRAC=%d ",(gpioreg[PLLB_CTRL]>>16) ,gpioreg[PLLB_CTRL]&0x3ff, gpioreg[PLLB_FRAC] ); - printf(" %f MHz\n",19.2* ((float)(gpioreg[PLLB_CTRL]&0x3ff) + ((float)gpioreg[PLLB_FRAC])/((float)(1<<20))) ); - printf("ARM=%d SP0=%d SP1=%d SP2=%d\n\n",gpioreg[PLLB_ARM],gpioreg[PLLB_SP0],gpioreg[PLLB_SP1],gpioreg[PLLB_SP2]); + // Sometimes calculated frequencies are off by a factor of 2 + // ANA1 bit 14 may indicate that a /2 prescaler is active + printf("PLLA PDIV=%d NDIV=%d FRAC=%d ", (gpioreg[PLLA_CTRL] >> 12)&0x7, gpioreg[PLLA_CTRL] & 0x3ff, gpioreg[PLLA_FRAC]); + printf(" %f MHz\n", 19.2 * ((float)(gpioreg[PLLA_CTRL] & 0x3ff) + ((float)gpioreg[PLLA_FRAC]) / ((float)(1 << 20)))); + printf("DSI0=%d CORE=%d PER=%d CCP2=%d\n\n", gpioreg[PLLA_DSI0], gpioreg[PLLA_CORE], gpioreg[PLLA_PER], gpioreg[PLLA_CCP2]); - printf("PLLC PDIV=%d NDIV=%d FRAC=%d ",(gpioreg[PLLC_CTRL]>>16) ,gpioreg[PLLC_CTRL]&0x3ff, gpioreg[PLLC_FRAC] ); - printf(" %f MHz\n",19.2* ((float)(gpioreg[PLLC_CTRL]&0x3ff) + ((float)gpioreg[PLLC_FRAC])/((float)(1<<20))) ); - printf("CORE2=%d CORE1=%d PER=%d CORE0=%d\n\n",gpioreg[PLLC_CORE2],gpioreg[PLLC_CORE1],gpioreg[PLLC_PER],gpioreg[PLLC_CORE0]); + printf("PLLB PDIV=%d NDIV=%d FRAC=%d ", (gpioreg[PLLB_CTRL] >> 12)&0x7, gpioreg[PLLB_CTRL] & 0x3ff, gpioreg[PLLB_FRAC]); + printf(" %f MHz\n", 19.2 * ((float)(gpioreg[PLLB_CTRL] & 0x3ff) + ((float)gpioreg[PLLB_FRAC]) / ((float)(1 << 20)))); + printf("ARM=%d SP0=%d SP1=%d SP2=%d\n\n", gpioreg[PLLB_ARM], gpioreg[PLLB_SP0], gpioreg[PLLB_SP1], gpioreg[PLLB_SP2]); - printf("PLLD %x PDIV=%d NDIV=%d FRAC=%d ",gpioreg[PLLD_CTRL],(gpioreg[PLLD_CTRL]>>16) ,gpioreg[PLLD_CTRL]&0x3ff, gpioreg[PLLD_FRAC] ); - printf(" %f MHz\n",19.2* ((float)(gpioreg[PLLD_CTRL]&0x3ff) + ((float)gpioreg[PLLD_FRAC])/((float)(1<<20))) ); - printf("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]>>16) ,gpioreg[PLLH_CTRL]&0x3ff, gpioreg[PLLH_FRAC] ); - printf(" %f MHz\n",19.2* ((float)(gpioreg[PLLH_CTRL]&0x3ff) + ((float)gpioreg[PLLH_FRAC])/((float)(1<<20))) ); - printf("AUX=%d RCAL=%d PIX=%d STS=%d\n\n",gpioreg[PLLH_AUX],gpioreg[PLLH_RCAL],gpioreg[PLLH_PIX],gpioreg[PLLH_STS]); + printf("PLLC PDIV=%d NDIV=%d FRAC=%d ", (gpioreg[PLLC_CTRL] >> 12)&0x7, gpioreg[PLLC_CTRL] & 0x3ff, gpioreg[PLLC_FRAC]); + printf(" %f MHz\n", 19.2 * ((float)(gpioreg[PLLC_CTRL] & 0x3ff) + ((float)gpioreg[PLLC_FRAC]) / ((float)(1 << 20)))); + printf("CORE2=%d CORE1=%d PER=%d CORE0=%d\n\n", gpioreg[PLLC_CORE2], gpioreg[PLLC_CORE1], gpioreg[PLLC_PER], gpioreg[PLLC_CORE0]); + printf("PLLD %x PDIV=%d NDIV=%d FRAC=%d ", gpioreg[PLLD_CTRL], (gpioreg[PLLD_CTRL] >> 12)&0x7, gpioreg[PLLD_CTRL] & 0x3ff, gpioreg[PLLD_FRAC]); + printf(" %f MHz\n", 19.2 * ((float)(gpioreg[PLLD_CTRL] & 0x3ff) + ((float)gpioreg[PLLD_FRAC]) / ((float)(1 << 20)))); + printf("DSI0=%d CORE=%d PER=%d DSI1=%d\n\n", gpioreg[PLLD_DSI0], gpioreg[PLLD_CORE], gpioreg[PLLD_PER], gpioreg[PLLD_DSI1]); + printf("PLLH PDIV=%d NDIV=%d FRAC=%d ", (gpioreg[PLLH_CTRL] >> 12)&0x7, gpioreg[PLLH_CTRL] & 0x3ff, gpioreg[PLLH_FRAC]); + printf(" %f MHz\n", 19.2 * ((float)(gpioreg[PLLH_CTRL] & 0x3ff) + ((float)gpioreg[PLLH_FRAC]) / ((float)(1 << 20)))); + printf("AUX=%d RCAL=%d PIX=%d STS=%d\n\n", gpioreg[PLLH_AUX], gpioreg[PLLH_RCAL], gpioreg[PLLH_PIX], gpioreg[PLLH_STS]); } void clkgpio::enableclk(int gpio) { - switch(gpio) + switch (gpio) { - case 4: gengpio.setmode(gpio,fsel_alt0);break; - case 20:gengpio.setmode(gpio,fsel_alt5);break; - case 32:gengpio.setmode(gpio,fsel_alt0);break; - case 34:gengpio.setmode(gpio,fsel_alt0);break; - default: fprintf(stderr,"gpio %d has no clk - available(4,20,32,34)\n",gpio);break; + case 4: + gengpio.setmode(gpio, fsel_alt0); + break; + case 20: + gengpio.setmode(gpio, fsel_alt5); + break; + case 32: + gengpio.setmode(gpio, fsel_alt0); + break; + case 34: + gengpio.setmode(gpio, fsel_alt0); + break; + default: + fprintf(stderr, "gpio %d has no clk - available(4,20,32,34)\n", gpio); + break; } usleep(100); } void clkgpio::disableclk(int gpio) { - gengpio.setmode(gpio,fsel_input); - + gengpio.setmode(gpio, fsel_input); } void clkgpio::Setppm(double ppm) { - clk_ppm=ppm-2.0; // -2 is empiric : FixMe + clk_ppm = ppm - 2.0; // -2 is empiric : FixMe } void clkgpio::SetppmFromNTP() @@ -472,85 +480,100 @@ void clkgpio::SetppmFromNTP() // ===================================================== ntx.modes = 0; /* only read */ - status = ntp_adjtime(&ntx); + status = ntp_adjtime(&ntx); double ntp_ppm; if (status != TIME_OK) { - fprintf(stderr,"Warning: NTP calibrate failed\n"); - - } - else - { - - ntp_ppm = (double)ntx.freq/(double)(1 << 16); - fprintf(stderr,"Info:NTP find ppm=%f\n",ntp_ppm); - if(fabs(ntp_ppm)<200) - Setppm(ntp_ppm); - } + fprintf(stderr, "Warning: NTP calibrate failed\n"); + } + else + { + + ntp_ppm = (double)ntx.freq / (double)(1 << 16); + fprintf(stderr, "Info:NTP find ppm=%f\n", ntp_ppm); + if (fabs(ntp_ppm) < 200) + Setppm(ntp_ppm); + } } - + // ************************************** GENERAL GPIO ***************************************************** -generalgpio::generalgpio():gpio(GetPeripheralBase()+GENERAL_BASE,GENERAL_LEN) +generalgpio::generalgpio() : gpio(GetPeripheralBase() + GENERAL_BASE, GENERAL_LEN) { } generalgpio::~generalgpio() { - } int generalgpio::setmode(uint32_t gpio, uint32_t mode) { - int reg, shift; + int reg, shift; - reg = gpio/10; - shift = (gpio%10) * 3; + reg = gpio / 10; + shift = (gpio % 10) * 3; - gpioreg[reg] = (gpioreg[reg] & ~(7<4096)||(FreqDivider<2)) fprintf(stderr,"Frequency out of range\n"); - fprintf(stderr,"PWM clk=%d / %d\n",FreqDivider,FreqFractionnal); - clk.gpioreg[PWMCLK_DIV] = 0x5A000000 | ((FreqDivider)<<12) | FreqFractionnal; - - usleep(100); - clk.gpioreg[PWMCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber|(1 << 4) ; //4 is STAR CLK - usleep(100); - - - SetPrediv(Prediv); //SetMode should be called before - return 0; + Prediv = 32; // Fixe for now , need investigation if not 32 !!!! FixMe ! + double Freqresult = (double)Pllfrequency / (double)(Frequency * Prediv); + uint32_t FreqDivider = (uint32_t)Freqresult; + uint32_t FreqFractionnal = (uint32_t)(4096 * (Freqresult - (double)FreqDivider)); + if ((FreqDivider > 4096) || (FreqDivider < 2)) + fprintf(stderr, "Frequency out of range\n"); + fprintf(stderr, "PWM clk=%d / %d\n", FreqDivider, FreqFractionnal); + clk.gpioreg[PWMCLK_DIV] = 0x5A000000 | ((FreqDivider) << 12) | FreqFractionnal; + usleep(100); + clk.gpioreg[PWMCLK_CNTL] = 0x5A000000 | (Mash << 9) | pllnumber | (1 << 4); //4 is STAR CLK + usleep(100); + + SetPrediv(Prediv); //SetMode should be called before + return 0; } void pwmgpio::SetMode(int Mode) { - if((Mode>=pwm1pin)&&(Mode<=pwm1pinrepeat)) - ModePwm=Mode; + if ((Mode >= pwm1pin) && (Mode <= pwm1pinrepeat)) + ModePwm = Mode; } int pwmgpio::SetPrediv(int predivisor) //Mode should be only for SYNC or a Data serializer : Todo { - Prediv=predivisor; - if(Prediv>32) - { - fprintf(stderr,"PWM Prediv is max 32\n"); - Prediv=2; - } - fprintf(stderr,"PWM Prediv %d\n",Prediv); - gpioreg[PWM_RNG1] = Prediv;// 250 -> 8KHZ - usleep(100); - gpioreg[PWM_RNG2] = Prediv;// 32 Mandatory for Serial Mode without gap - - //gpioreg[PWM_FIFO]=0xAAAAAAAA; + Prediv = predivisor; + if (Prediv > 32) + { + fprintf(stderr, "PWM Prediv is max 32\n"); + Prediv = 2; + } + fprintf(stderr, "PWM Prediv %d\n", Prediv); + gpioreg[PWM_RNG1] = Prediv; // 250 -> 8KHZ + usleep(100); + gpioreg[PWM_RNG2] = Prediv; // 32 Mandatory for Serial Mode without gap + + //gpioreg[PWM_FIFO]=0xAAAAAAAA; + + gpioreg[PWM_DMAC] = PWMDMAC_ENAB | PWMDMAC_THRSHLD; + usleep(100); + gpioreg[PWM_CTL] = PWMCTL_CLRF; + usleep(100); + + //gpioreg[PWM_CTL] = PWMCTL_USEF1| PWMCTL_MODE1| PWMCTL_PWEN1|PWMCTL_MSEN1; + switch (ModePwm) + { + case pwm1pin: + gpioreg[PWM_CTL] = PWMCTL_USEF1 | PWMCTL_MODE1 | PWMCTL_PWEN1 | PWMCTL_MSEN1; + break; // All serial go to 1 pin + case pwm2pin: + gpioreg[PWM_CTL] = PWMCTL_USEF2 | PWMCTL_PWEN2 | PWMCTL_MODE2 | PWMCTL_USEF1 | PWMCTL_MODE1 | PWMCTL_PWEN1; + break; // Alternate bit to pin 1 and 2 + case pwm1pinrepeat: + gpioreg[PWM_CTL] = PWMCTL_USEF1 | PWMCTL_MODE1 | PWMCTL_PWEN1 | PWMCTL_RPTL1; + break; // All serial go to 1 pin, repeat if empty : RF mode with PWM + } + usleep(100); - gpioreg[PWM_DMAC] = PWMDMAC_ENAB | PWMDMAC_THRSHLD; - usleep(100); - gpioreg[PWM_CTL] = PWMCTL_CLRF; - usleep(100); - - //gpioreg[PWM_CTL] = PWMCTL_USEF1| PWMCTL_MODE1| PWMCTL_PWEN1|PWMCTL_MSEN1; - switch(ModePwm) - { - case pwm1pin:gpioreg[PWM_CTL] = PWMCTL_USEF1| PWMCTL_MODE1| PWMCTL_PWEN1|PWMCTL_MSEN1;break; // All serial go to 1 pin - case pwm2pin:gpioreg[PWM_CTL] = PWMCTL_USEF2|PWMCTL_PWEN2|PWMCTL_MODE2|PWMCTL_USEF1| PWMCTL_MODE1| PWMCTL_PWEN1;break;// Alternate bit to pin 1 and 2 - case pwm1pinrepeat:gpioreg[PWM_CTL] = PWMCTL_USEF1| PWMCTL_MODE1| PWMCTL_PWEN1|PWMCTL_RPTL1;break; // All serial go to 1 pin, repeat if empty : RF mode with PWM - } - usleep(100); - return 0; - } - + // ********************************** PCM GPIO (I2S) ********************************** -pcmgpio::pcmgpio():gpio(GetPeripheralBase()+PCM_BASE,PCM_LEN) +pcmgpio::pcmgpio() : gpio(GetPeripheralBase() + PCM_BASE, PCM_LEN) { - gpioreg[PCM_CS_A] = 1; // Disable Rx+Tx, Enable PCM block + gpioreg[PCM_CS_A] = 1; // Disable Rx+Tx, Enable PCM block } pcmgpio::~pcmgpio() { - } -int pcmgpio::SetPllNumber(int PllNo,int MashType) +int pcmgpio::SetPllNumber(int PllNo, int MashType) { - if(PllNo<8) - pllnumber=PllNo; + if (PllNo < 8) + pllnumber = PllNo; else - pllnumber=clk_pllc; - if(MashType<4) - Mash=MashType; + pllnumber = clk_pllc; + if (MashType < 4) + Mash = MashType; else - Mash=0; - clk.gpioreg[PCMCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber|(1 << 4) ; //4 is START CLK - Pllfrequency=GetPllFrequency(pllnumber); + Mash = 0; + clk.gpioreg[PCMCLK_CNTL] = 0x5A000000 | (Mash << 9) | pllnumber | (1 << 4); //4 is START CLK + Pllfrequency = GetPllFrequency(pllnumber); return 0; } uint64_t pcmgpio::GetPllFrequency(int PllNo) { return clk.GetPllFrequency(PllNo); - } int pcmgpio::ComputePrediv(uint64_t Frequency) { - int prediv=5; - for(prediv=10;prediv<1000;prediv++) + int prediv = 5; + for (prediv = 10; prediv < 1000; prediv++) { - double Freqresult=(double)Pllfrequency/(double)(Frequency*prediv); - if((Freqresult<4096.0)&&(Freqresult>2.0)) + double Freqresult = (double)Pllfrequency / (double)(Frequency * prediv); + if ((Freqresult < 4096.0) && (Freqresult > 2.0)) { - fprintf(stderr,"PCM prediv = %d\n",prediv); + fprintf(stderr, "PCM prediv = %d\n", prediv); break; } - } - return prediv; + } + return prediv; } int pcmgpio::SetFrequency(uint64_t Frequency) { - Prediv=ComputePrediv(Frequency); - double Freqresult=(double)Pllfrequency/(double)(Frequency*Prediv); - uint32_t FreqDivider=(uint32_t)Freqresult; - uint32_t FreqFractionnal=(uint32_t) (4096*(Freqresult-(double)FreqDivider)); - fprintf(stderr,"PCM clk=%d / %d\n",FreqDivider,FreqFractionnal); - if((FreqDivider>4096)||(FreqDivider<2)) fprintf(stderr,"PCM Frequency out of range\n"); - clk.gpioreg[PCMCLK_DIV] = 0x5A000000 | ((FreqDivider)<<12) | FreqFractionnal; + Prediv = ComputePrediv(Frequency); + double Freqresult = (double)Pllfrequency / (double)(Frequency * Prediv); + uint32_t FreqDivider = (uint32_t)Freqresult; + uint32_t FreqFractionnal = (uint32_t)(4096 * (Freqresult - (double)FreqDivider)); + fprintf(stderr, "PCM clk=%d / %d\n", FreqDivider, FreqFractionnal); + if ((FreqDivider > 4096) || (FreqDivider < 2)) + fprintf(stderr, "PCM Frequency out of range\n"); + clk.gpioreg[PCMCLK_DIV] = 0x5A000000 | ((FreqDivider) << 12) | FreqFractionnal; SetPrediv(Prediv); return 0; - } int pcmgpio::SetPrediv(int predivisor) //Carefull we use a 10 fixe divisor for now : frequency is thus f/10 as a samplerate { - if(predivisor>1000) + if (predivisor > 1000) { - fprintf(stderr,"PCM prediv should be <1000"); - predivisor=1000; + fprintf(stderr, "PCM prediv should be <1000"); + predivisor = 1000; } - - gpioreg[PCM_TXC_A] = 0<<31 | 1<<30 | 0<<20 | 0<<16; // 1 channel, 8 bits + + gpioreg[PCM_TXC_A] = 0 << 31 | 1 << 30 | 0 << 20 | 0 << 16; // 1 channel, 8 bits usleep(100); - + //printf("Nb PCM STEP (<1000):%d\n",NbStepPCM); - gpioreg[PCM_MODE_A] = (predivisor-1)<<10; // SHOULD NOT EXCEED 1000 !!! + gpioreg[PCM_MODE_A] = (predivisor - 1) << 10; // SHOULD NOT EXCEED 1000 !!! usleep(100); - gpioreg[PCM_CS_A] |= 1<<4 | 1<<3; // Clear FIFOs + gpioreg[PCM_CS_A] |= 1 << 4 | 1 << 3; // Clear FIFOs usleep(100); - gpioreg[PCM_DREQ_A] = 64<<24 | 64<<8 ; //TX Fifo PCM=64 DMA Req when one slot is free? + gpioreg[PCM_DREQ_A] = 64 << 24 | 64 << 8; //TX Fifo PCM=64 DMA Req when one slot is free? usleep(100); - gpioreg[PCM_CS_A] |= 1<<9; // Enable DMA + gpioreg[PCM_CS_A] |= 1 << 9; // Enable DMA usleep(100); - gpioreg[PCM_CS_A] |= 1<<2; //START TX PCM - + gpioreg[PCM_CS_A] |= 1 << 2; //START TX PCM + return 0; - } - // ********************************** PADGPIO (Amplitude) ********************************** -padgpio::padgpio():gpio(GetPeripheralBase()+PADS_GPIO,PADS_GPIO_LEN) +padgpio::padgpio() : gpio(GetPeripheralBase() + PADS_GPIO, PADS_GPIO_LEN) { - } padgpio::~padgpio() { - } - - - diff --git a/src/phasedmasync.cpp b/src/phasedmasync.cpp index fedef3f..5098e0c 100644 --- a/src/phasedmasync.cpp +++ b/src/phasedmasync.cpp @@ -44,9 +44,10 @@ phasedmasync::phasedmasync(uint64_t TuneFrequency,uint32_t SampleRate,int Number fprintf(stderr,"PWM Mult %d Frac %d Div %d\n",IntMultiply,FracMultiply,clkgpio::PllFixDivider); - pwmgpio::clk.gpioreg[PWMCLK_DIV] = 0x5A000000 | ((clkgpio::PllFixDivider)<<12); // PWM clock input divider + pwmgpio::clk.gpioreg[PWMCLK_DIV] = 0x5A000000 | ((clkgpio::PllFixDivider)<<12) |pwmgpio::pllnumber; // PWM clock input divider usleep(100); - pwmgpio::clk.gpioreg[PWMCLK_CNTL]= 0x5A000000 | (pwmgpio::Mash << 9) | pwmgpio::pllnumber|(1 << 4) ; //4 is START CLK + + pwmgpio::clk.gpioreg[PWMCLK_CNTL]= 0x5A000000 | (pwmgpio::Mash << 9) | ((clkgpio::PllFixDivider)<<12)| pwmgpio::pllnumber|(1 << 4) ; //4 is START CLK usleep(100); pwmgpio::SetPrediv(32); //SetMode should be called before diff --git a/src/serialdmasync.cpp b/src/serialdmasync.cpp index 9df6c2c..675fe45 100644 --- a/src/serialdmasync.cpp +++ b/src/serialdmasync.cpp @@ -48,11 +48,7 @@ serialdmasync::serialdmasync(uint32_t SampleRate,int Channel,uint32_t FifoSize,b SetDmaAlgo(); - - // Note : Spurious are at +/-(19.2MHZ/2^20)*Div*N : (N=1,2,3...) So we need to have a big div to spurious away BUT - // Spurious are ALSO at +/-(19.2MHZ/2^20)*(2^20-Div)*N - // Max spurious avoid is to be in the center ! Theory shoud be that spurious are set away at 19.2/2= 9.6Mhz ! But need to get account of div of PLLClock - + } serialdmasync::~serialdmasync()