//function to init GPIO 18 19 20 21 and set in ALT0 for PCM
static void init_pcm_gpio()
{
unsigned int FSEL1 = *(volatile unsigned*)GPFSEL1; //GPIO 18 - 19
unsigned int FSEL2 = *(volatile unsigned*)GPFSEL2; //GPIO 20 - 21
FSEL1 &= ~((0b111) << 24) | ((0b111) << 27);
FSEL2 &= ~((0b111) | ((0b111) << 3));
FSEL1 |= ((0b100 << 24) | (0b100 << 27));
FSEL2 |= ((0b100) | (0b100 << 3));
*(volatile unsigned*)GPFSEL1 = FSEL1;
*(volatile unsigned*)GPFSEL2 = FSEL2;
*(volatile unsigned*)GPPUD = 0;
delay(150);
*(volatile unsigned*)GPPUDCLK0 = (1 << 18 | 1 << 19 | 1 << 20 | 1 << 21);
delay(150);
*(volatile unsigned*)GPPUDCLK0 = 0;
}
_______________________________________________________________________
//function to choose the good clock to use with the good divider for the Bit clock
static void init_pcm_clock()
{
*(volatile unsigned*)CM_PCMCTL = CM_PASSWORD | 0x1;
while ( *(volatile unsigned*)CM_PCMCTL & 0x80); //wait busy
//DIVI = 13, DIVF = 2480
//Password | (DIVI << 12) | DIVF
*(volatile unsigned*)CM_PCMDIV = CM_PASSWORD | (13 << 12) | 2480;
// Source: 1 (OSC), MASH: 1 (pour le fractionnaire), ENAB: 1
*(volatile unsigned*)CM_PCMCTL = CM_PASSWORD | (1 << 9) | (1 << 4) | 0x1;
}
_________________________________________________________________________
//function to init the PCM module and set all hardware register
static void init_pcm()
{
/* Disable PCM */
*(volatile unsigned*)PCM_CS_A = 0;
unsigned mode_a = 0;
mode_a &= ~(1 << 28); //enable PCM clock
mode_a &= ~(1 << 23); //Master PCM Mclock
mode_a &= ~(1 << 21); //Master PCM Fclock
mode_a |= (31 << 10); //number of clock need (31+1)
mode_a |= (16 << 0); //nombre de clock
*(volatile unsigned*)PCM_MODE_A = mode_a;
unsigned tx_a = 0;
tx_a |= (1 << 30); //enable chanel 1
tx_a |= (8 << 16); //width of 16bits for chanel 1
tx_a |= (0 << 20); //position 0
tx_a |= (1 << 14); //enable chanel 2
tx_a |= (8 << 0); //width of 16bits for chanel 2
tx_a |= (16 << 4); //position of the value to chanel 2 to send
*(volatile unsigned*)PCM_TXC_A = tx_a;
unsigned cs_a = 0;
cs_a |= 1 << 2; //enable transimission
cs_a |= 1; //enable PCM module
*(volatile unsigned*)PCM_CS_A = cs_a;
}
___________________________________________________________________________
//function to fill the FIFO if it is not full
void send_data_to_pcm(unsigned data) {
if ((*(volatile unsigned*)PCM_CS_A) & (1 << 19)) //FIFO not full
*(volatile unsigned *)PCM_FIFO_A = data;
}
___________________________________________________________________________
//kernel main to send data in the FIFO of the PCM
init_I2S();
//enable_irq();
printf("kernel boots...\r\n");
unsigned cptr = 0;
while (1){
printf("loop..\r\n");
if ((cptr & 1) == 0) {
send_data_to_pcm(0xFFFF);
} else {
send_data_to_pcm(0x0);
}
cptr++;
}