hello, im tring to make 16 bits music with an arduino due. The samples are played in an interrupt, but in don’t managed to get a frequency sufficiently high.
for the TC_SetRC(TC0, 1, 400); if i write a number under 400 for TIMER_CLOCK3 it doesn’t work. And for each other timer clock, i can’t get under something like 6500 Hz for the music.
Here is the program, just look at the ISR and the timer setup:
#include <SdFat.h>
SdFat sd;
SdFile file;
#define BUF_SIZE 10000//taille des buffers (doit être pair)
uint8_t buffer0[BUF_SIZE];
uint8_t buffer1[BUF_SIZE];
volatile uint32_t var32;//variable 32bits qui contient le nombre 32 bits à écrire sur les registres
volatile boolean num_buff_lec=0;//variable qui dicte le choix du buffer qui est lu
volatile boolean auto_remp_buffer=0;
volatile boolean numerobufferecr=1;
volatile int tetelecture=0;
unsigned int i=0;
void setup()
{
//TIMER
/* activation du peripherique TC dans le Power Management Controller */
PMC->PMC_WPMR = PMC_WPMR_WPKEY_VALUE;//on desactive la write protection des registres en entrant la clé dans le registre PMC_WPMR
PMC->PMC_PCER0 = 1 << 28;//on active le TC_3 dont l'identifiant est 30, il est donc controlé par le PMC_PCER0 au bit 30
/*on configure le timer*/
TC0->TC_CHANNEL[1].TC_CMR = TC_CMR_WAVE // Waveform mode
| TC_CMR_WAVSEL_UP_RC // UP mode with automatic trigger on RC Compare
| TC_CMR_TCCLKS_TIMER_CLOCK3; // MCK/2 = 42 M Hz, clk on rising edge
TC0->TC_CHANNEL[1].TC_RC = 400;//on choisi la valeur du registre C TC_RC
TC0->TC_CHANNEL[1].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN;//démarre le timer avec le registre TC_CCR
// enable timer interrupts on the timer
TC0->TC_CHANNEL[1].TC_IER=TC_IER_CPCS; //IER = interrupt enable register; on écrit sur le registre TC_IER pour autoriser les interuptions liées à la comparaison avec le registre C, ici on active les interruptions du timer pour la comparaison avec le registre C; TC_CHANNEL est un tableau de type TcChannel dans la structure Tc, c'est une structure dans une structure, c'est pourquoi il y a la fleche pour le pointeur puis le point pour l'elements de structure
/* on active le nested vector interrupt controller qui controle toutes les interruptions*/
NVIC_EnableIRQ(TC1_IRQn);
//SD SPI
/* Initialisation du port série*/
//Serial.begin(9600);
/* Initialisation du port SPI */
pinMode(10, OUTPUT);
if (!sd.begin(10, SPI_FULL_SPEED))
{
//Serial.println("FAIL CONNEXION");
for(;;);
}
file.open("test.raw", O_READ);//on ouvre le fichier
file.read(buffer0, BUF_SIZE);
file.read(buffer1, BUF_SIZE);
//REGISTRES PIO
/* activation du peripherique TC dans le Power Management Controller */
PMC->PMC_PCER0 = 1 << 13;
PIOC->PIO_PER = 0b00000000000001111111001111111110;
PIOC->PIO_OER = 0b00000000000001111111001111111110;
PIOC->PIO_OWER = 0b00000000000001111111001111111110;
PIOC->PIO_OWDR = 0b11111111111110000000110000000001;
}
void loop()
{
if(auto_remp_buffer==1)//si on a l'autorisation de remplir le buffer qui vient d'être lu
{
if(num_buff_lec==0){file.read(buffer1, BUF_SIZE);}//on rempli le buffer 0
else{file.read(buffer0, BUF_SIZE);}//on rempli le buffer 1
auto_remp_buffer=0;
}
}
void TC1_Handler()//ISR
{
TC0->TC_CHANNEL[1].TC_SR;//on lit la valeur du registre TC_SR (status register), pour qu'il se remette à zero
if(!num_buff_lec){ var32 = ((uint16_t)buffer0[tetelecture+1]<<8) | (buffer0[tetelecture]); }
else{ var32 = ((uint16_t)buffer1[tetelecture+1]<<8) | (buffer1[tetelecture]); }
PIOC->PIO_ODSR = ((var32 & 0b1111111000000000)<<3) | ((var32 & 0b0000000111111111)<<1);
tetelecture+=2;
if(tetelecture>=BUF_SIZE)//quand on fini un buffer
{
num_buff_lec=!num_buff_lec;//on passe à l'autre buffer
tetelecture=0;//on reprend au début de l'autre buffer
auto_remp_buffer=1;//on donne l'autorisation de remplir le buffer qui vient dêtre lu
}
}
thanks