From 7fef1e0c8d0df83909de29218498eac1b6c9ea1d Mon Sep 17 00:00:00 2001 From: F5OEO Date: Tue, 27 Feb 2018 10:13:10 +0000 Subject: [PATCH] add pcm --- src/gpio.cpp | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++-- src/gpio.h | 36 +++++++++++++++++++++++++-- 2 files changed, 102 insertions(+), 4 deletions(-) diff --git a/src/gpio.cpp b/src/gpio.cpp index de7ba90..3a49279 100644 --- a/src/gpio.cpp +++ b/src/gpio.cpp @@ -99,7 +99,7 @@ int clkgpio::SetFrequency(uint64_t Frequency) double Freqresult=(double)Pllfrequency/(double)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); gpioreg[GPCLK_DIV] = 0x5A000000 | ((FreqDivider)<<12) | FreqFractionnal; @@ -231,6 +231,7 @@ pwmgpio::pwmgpio():gpio(GetPeripheralBase()+PWM_BASE,PWM_LEN) pwmgpio::~pwmgpio() { gpioreg[PWM_CTL] = 0; + gpioreg[PWM_DMAC] = 0; } int pwmgpio::SetPllNumber(int PllNo,int MashType) @@ -260,13 +261,14 @@ int pwmgpio::SetFrequency(uint64_t Frequency) double Freqresult=(double)Pllfrequency/(double)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"); clk.gpioreg[PWMCLK_DIV] = 0x5A000000 | ((FreqDivider)<<12) | FreqFractionnal; return 0; } -int pwmgpio::SetMode(int Mode) +int pwmgpio::SetMode(int Mode) //Mode should be only for SYNC or a Data serializer : Todo { gpioreg[PWM_RNG1] = 32;// 250 -> 8KHZ usleep(100); @@ -284,4 +286,68 @@ int pwmgpio::SetMode(int Mode) } +// ********************************** PCM GPIO (I2S) ********************************** +pcmgpio::pcmgpio():gpio(GetPeripheralBase()+PCM_BASE,PCM_LEN) +{ + gpioreg[PCM_CS_A] = 1; // Disable Rx+Tx, Enable PCM block +} + +pcmgpio::~pcmgpio() +{ + +} + +int pcmgpio::SetPllNumber(int PllNo,int MashType) +{ + if(PllNo<8) + pllnumber=PllNo; + else + 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); + return 0; +} + +uint64_t pcmgpio::GetPllFrequency(int PllNo) +{ + return clk.GetPllFrequency(PllNo); + +} + +int pcmgpio::SetFrequency(uint64_t Frequency) +{ + + double Freqresult=(double)Pllfrequency/(double)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"); + clk.gpioreg[PCMCLK_DIV] = 0x5A000000 | ((FreqDivider)<<12) | FreqFractionnal; + + return 0; + +} + +int pcmgpio::SetMode(int Mode) //Carefull we use a 10 fixe divisor for now : frequency is thus f/10 as a samplerate +{ + gpioreg[PCM_TXC_A] = 0<<31 | 1<<30 | 0<<20 | 0<<16; // 1 channel, 8 bits + usleep(100); + int NbStepPCM = 10; + //printf("Nb PCM STEP (<1000):%d\n",NbStepPCM); + gpioreg[PCM_MODE_A] = (NbStepPCM-1)<<10; // SHOULD NOT EXCEED 1000 !!! + usleep(100); + 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? + usleep(100); + gpioreg[PCM_CS_A] |= 1<<9; // Enable DMA + usleep(100); + gpioreg[PCM_CS_A] |= 1<<2; //START TX PCM + + return 0; + +} diff --git a/src/gpio.h b/src/gpio.h index 778d866..4a1169c 100644 --- a/src/gpio.h +++ b/src/gpio.h @@ -156,8 +156,8 @@ class generalgpio:public gpio #define PWM_RNG2 (0x20/4) #define PWM_FIFO (0x18/4) -#define PWMCLK_CNTL (0x100/4) // Clk register -#define PWMCLK_DIV (0x104/4) // Clk register +#define PWMCLK_CNTL (40) // Clk register +#define PWMCLK_DIV (41) // Clk register #define PWMCTL_MSEN2 (1<<15) @@ -192,5 +192,37 @@ class pwmgpio:public gpio int SetMode(int Mode); }; +//******************************* PCM GPIO (I2S) *********************************** +#define PCM_BASE (0x00203000) +#define PCM_LEN 0x24 + +#define PCM_CS_A (0x00/4) +#define PCM_FIFO_A (0x04/4) +#define PCM_MODE_A (0x08/4) +#define PCM_RXC_A (0x0c/4) +#define PCM_TXC_A (0x10/4) +#define PCM_DREQ_A (0x14/4) +#define PCM_INTEN_A (0x18/4) +#define PCM_INT_STC_A (0x1c/4) +#define PCM_GRAY (0x20/4) + +#define PCMCLK_CNTL (38) // Clk register +#define PCMCLK_DIV (39) // Clk register + +class pcmgpio:public gpio +{ + protected: + clkgpio clk; + int pllnumber; + int Mash; + uint64_t Pllfrequency; + public: + pcmgpio(); + ~pcmgpio(); + int SetPllNumber(int PllNo,int MashType); + uint64_t GetPllFrequency(int PllNo); + int SetFrequency(uint64_t Frequency); + int SetMode(int Mode); +}; #endif