diff --git a/GASSP72/Manuel_utilisateur_GASSP72_v7.pdf b/GASSP72/Manuel_utilisateur_GASSP72_v7.pdf new file mode 100644 index 0000000..e146140 Binary files /dev/null and b/GASSP72/Manuel_utilisateur_GASSP72_v7.pdf differ diff --git a/GASSP72/gassp72.h b/GASSP72/gassp72.h new file mode 100644 index 0000000..6cfaee4 --- /dev/null +++ b/GASSP72/gassp72.h @@ -0,0 +1,115 @@ +/** + * Bibliotheque GASSP 2013-02-15 + * + * GPIO - ADC - Sequenceur - System Timer - PWM - 72 MHz + * + */ + +// STM32F10X_CL : pour le STM32F107 "Communication Line" +// STM32F10X_MD : pour le STM32F103 "Medium Density" + +//#define STM32F10X_MD // 2019 fix for Keil 5.23 + +#include "stm32f10x.h" + +// horloge systeme (config statique a 72 MHz pour le STM32F103) ------------ +void CLOCK_Configure(void); + +// Timers 1, 2, 3, 4 ------------------------------------------------------- +// la duree entre deux debordements successifs doit etre donnnee en periodes +// d'horloge CPU (typiquement 72 MHz) +void Timer_1234_Init_ff( TIM_TypeDef *Timer, u32 Duree_ticks ); + +// activation d'une fonction de traitement de l'interruption timer (callback) +void Active_IT_Debordement_Timer( TIM_TypeDef *Timer, char Prio, void (*IT_function)(void) ); + +// bloque le timer +#define Bloque_Timer(Timer) Timer->CR1=(Timer->CR1)&~(1<<0) + +// Lance timer +#define Run_Timer(Timer) Timer->CR1=(Timer->CR1)|(1<<0) + +// PWM (basee sur un des Timers 1, 2, 3, 4 --------------------------------- +// la periode doit etre donnee en periodes d'horloge CPU (typiquement 72 MHz) +// la fonction rend la pleine echelle ou resolution, c'est a dire la plage +// de valeurs acceptees pour moduler la largeur d'impulsion +vu16 PWM_Init_ff( TIM_TypeDef *Timer, char Voie, u32 Periode_ticks ); + +// Timer systeme "SysTick" ------------------------------------------------- + +// la periode doit etre donnee en periodes d'horloge CPU (typiquement 72 MHz) +void Systick_Period_ff( unsigned int Periode_ticks ); + +// activation d'une fonction de traitement de l'interruption timer (callback) +void Systick_Prio_IT( char Prio, void (*Systick_function)(void) ); + +#define SysTick_On ((SysTick->CTRL)=(SysTick->CTRL)|1<<0) +#define SysTick_Off ((SysTick->CTRL)=(SysTick->CTRL)& ~(1<<0)) +#define SysTick_Enable_IT ((SysTick->CTRL)=(SysTick->CTRL)|1<<1) +#define SysTick_Disable_IT ((SysTick->CTRL)=(SysTick->CTRL)& ~(1<<1)) + +// ADC - DMA --------------------------------------------------------------- +// Analog-to-Digital Conversion, Direct Memory Access + +// la duree d'echantillonnage doit etre donnee en periodes d'horloge CPU (typiquement 72 MHz) +// la fonction rend la duree totale de conversion (meme unites) +u32 Init_TimingADC_ActiveADC_ff( ADC_TypeDef * ADC, u32 Duree_Ech_ticks ); + +// choix d'un canal ADC unique +void Single_Channel_ADC( ADC_TypeDef * ADC, char Voie_ADC ); + +// la periode de repetition des acquisitions doit etre donnee en periodes d'horloge CPU +// Les sources de déclenchement possibles : +#define TIM1_CC1 0 +#define TIM1_CC2 1 +#define TIM1_CC3 2 +#define TIM2_CC2 3 +#define TIM4_CC4 5 +void Init_Conversion_On_Trig_Timer_ff( ADC_TypeDef * ADC, char Source, u32 Periode_ticks ); + +// initialisation d'acquisition en mode DMA +// Ptr_Table_DMA doit pointer sur un espace memoire suffisant pour le nombre d'ech. demande +void Init_ADC1_DMA1( char Circ, vu16 *Ptr_Table_DMA ); + + +// Lance une DMA sur le nombre de points spécifie. Les resultats seront stockes +// dans la zone de RAM écrite est indiquée lors de l'appel de la fonction Init_ADC1_DMA1 +void Start_DMA1( u16 NbEchDMA ); + +// arret DMA +#define Stop_DMA1 DMA1_Channel1->CCR =(DMA1_Channel1->CCR) &~0x1; + +// fonction d'attente (bloquante) +// la duree depend de la periode d'acquisition et du nombre d'echantillons +void Wait_On_End_Of_DMA1(void); + + +// GPIO -------------------------------------------------------------------- + +// Sens +#define INPUT 'i' +#define OUTPUT 'o' + +// Techno pour pin en entrée (INPUT) +#define ANALOG 0 +#define INPUT_FLOATING 1 +#define INPUT_PULL_DOWN_UP 2 + +// Techno pour pin en sortie (OUTPUT) +#define OUTPUT_PPULL 0 +#define OUTPUT_OPDRAIN 1 +#define ALT_PPULL 2 +#define ALT_OPDRAIN 3 + +// La fonction initialise n'importe quelle broche de port (entrée, sortie, techno....) +// Exemple : +// Port_IO_Init(GPIOB, 8, OUTPUT, OUTPUT_PPULL); +// Place le bit 8 du port B en sortie Push-pull +// Renvoie 0 si tout est OK, et 1 s'il y a un problème (plage d'entrée non respectée) +char GPIO_Configure(GPIO_TypeDef * Port, int Broche, int Sens, int Techno); + +// Spécifier le numéro de broche (0 à 15) +// exemple : Port_IO_Set(GPIOB,8); +#define GPIO_Set(GPIO,Broche) GPIO->BSRR=(0x01<BRR=(0x01< 0 `TIM3_CCR3 - 0080000000000000000000000000E0FFFFFFEF410000000000000000000000000000000054494D335F4343523300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000001000000000000000000F03F1200000000000000000000000000000000000000BA1E0008 + 00800000000000000000000000000000007076400000000000000000000000000000000054494D335F4343523300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000001000000000000000000F03F1100000000000000000000000000000000000000981E0008 @@ -268,8 +268,8 @@ 0 0 0 - .\Src\signalCarre.s - signalCarre.s + .\Src\gestionSon.s + gestionSon.s 0 0 @@ -316,18 +316,6 @@ 3 5 - 4 - 0 - 0 - 0 - ..\GASSP72\gassp72.lib - gassp72.lib - 0 - 0 - - - 3 - 6 2 0 0 @@ -337,6 +325,18 @@ 0 0 + + 3 + 6 + 4 + 0 + 0 + 0 + .\GASSP72\gassp72.lib + gassp72.lib + 0 + 0 + diff --git a/Project.uvprojx b/Project.uvprojx index 8472fa1..ebd090a 100644 --- a/Project.uvprojx +++ b/Project.uvprojx @@ -338,7 +338,7 @@ --C99 STM32F103xB,USE_FULL_LL_DRIVER - ../GASSP72 + ./GASSP72 @@ -388,9 +388,9 @@ .\Src\principal.c - signalCarre.s + gestionSon.s 2 - .\Src\signalCarre.s + .\Src\gestionSon.s @@ -412,16 +412,16 @@ 5 .\Src\etat.h - - gassp72.lib - 4 - ..\GASSP72\gassp72.lib - son.asm 2 .\Src\son.asm + + gassp72.lib + 4 + .\GASSP72\gassp72.lib + diff --git a/README.md b/README.md index f51d68e..ee698cf 100644 --- a/README.md +++ b/README.md @@ -4,27 +4,9 @@ Binôme : Cavailles Kévin / Dumaz Clément Classe : 3_MIC_C -Objectif 2 DFT en réel et gestion du score des 6 joueurs : +Objectif 3 Gestion du son : --Le signal peut être réglé via le parametre Duree_Ech_ticks de Init_TimingADC_ActiveADC_ff(). -Ce parametre peut prendre les valeurs de 48 a 83 (0x30 a 0x53). - --Afin de visualiser le bon fonctionnement de la DFT en mode débogage, il est recommandé de mettre 2 points d’arrêts dans le fichier Src/calcul_dft.s. Un à la ligne 29 et un à la ligne 60. -3 clicks sur “run†(F5), en mode débogage, correspondront à 1 DFT complète. Les 2 premiers “run†permettront de visualiser la partie réelle puis la partie imaginaire. Le 3ème “run†permettra de visualiser le résultat de la DFT. +-Afin de visualiser le bon fonctionnement de la gestion du son en mode débogage, il est recommandé de mettre 1 point d’arrêt dans le fichier Src/gestionSon.s. Un à la ligne 19. +Cliquez 1 fois sur run afin que le programme s'arrête au point d'arrêt. En bas à droite de l'éditeur, il doit y avoir un chronomètre se présentant sous la forme "t1: x.xxx sec". +Click droit sur ce chronomètre -> "Reset Stop Watch(t1)". Cliquez sur "Run" 1 fois, le chronomètre devrait afficher "t1 : 0.00009100 sec". --Afin de visualiser le bon fonctionnement du système de score, il est recommandé de ne mettre aucun point d'arrêt et d'observer -la variable "scores" en mode débogage. -Pour ce faire : -- mode débogage -> Src/principal.c ligne 21 click droit sur scores -> Add 'scores[taille]' to ... -> Watch 1. -- "scores[6]" devrait apparaître dans Watch 1. Retirez "[6]" afin de pouvoir visualiser le tableau en entier. -- Cliquez sur "+" directement à droite de "scores". -- Cliquez sur "run", vous devriez voir le tableau de score se remplir peu à peu (ou non) en fonction du signal choisi. - --En l'état (avec 0x33), les scores doivent être les suivants : -* J1 (scores[0]) : 1 -* J2 (scores[1]) : 2 -* J3 (scores[2]) : 3 -* J4 (scores[3]) : 4 -* J5 (scores[4]) : 5 -* J6 (scores[5]) : 0 - diff --git a/Src/gestionSon.s b/Src/gestionSon.s new file mode 100644 index 0000000..59b8d5e --- /dev/null +++ b/Src/gestionSon.s @@ -0,0 +1,48 @@ +; ce programme est pour l'assembleur RealView (Keil) + thumb + area moncode, code, readonly + export timer_callback + extern etat +; +E_POS equ 0 +E_TAI equ 4 +E_SON equ 8 +E_RES equ 12 +E_PER equ 16 + +COMPOSANTE_CONTINUE equ 32768 + +TIM3_CCR3 equ 0x4000043C ; adresse registre PWM + +timer_callback proc + + push{r4} + + ldr r1, =etat ;Chargement de la structure etat + ldr r2, [r1, #E_POS] ;Récupération de la position actuelle + + ldr r3, [r1,#E_TAI] ;Récupération de la taille du fichier de son + cmp r2, r3 ;Si position >= taille + bge silence ;On a lu tous les échantillons et on termine la procédure + ldr r4, [r1, #E_RES] ;Sinon, on charge la résolution, + ldr r3, [r1, #E_SON] ;Le tableau de son, puis l'échantillon + ldrsh r3, [r3, r2,lsl #1] + + + add r3, r3, #COMPOSANTE_CONTINUE ;On ajoute la composante continue + mul r3, r3, r4 ;On multiplie par la résolution + lsr r3, #16 ;Puis on divise par 2^16 + + ldr r4, =TIM3_CCR3 ;On stocke ensuite le résultat dans le TIM3_CCR3 de 32 bits + str r3, [r4] + + add r2,#1 ;On incrémente ensuite la position pour l'échantillon suivant + str r2,[r1, #E_POS] + +silence + + pop{r4} + bx lr + endp + end + \ No newline at end of file diff --git a/Src/makefile b/Src/makefile deleted file mode 100644 index 5b5625e..0000000 --- a/Src/makefile +++ /dev/null @@ -1,27 +0,0 @@ -# makefile pour MinGW - -CCOPT = -Wall -O2 -C_SRC = wav_head.c appli.c -CPP_SRC = -EXE = wav2asm.exe - -OBJS = $(C_SRC:.c=.o) $(CPP_SRC:.cpp=.o) - -# linkage -$(EXE) : $(OBJS) - g++ -o $(EXE) $(OBJS) - -# compilage -.c.o : - gcc $(CCOPT) -c $< - -.cpp.o : - g++ $(CCOPT) -c $< -# other - -clean : - del *.o; del *.exe - -# dependances : -wav_head.o : wav_head.h -appli.o : wav_head.h diff --git a/Src/principal.c b/Src/principal.c index f984696..25d8562 100644 --- a/Src/principal.c +++ b/Src/principal.c @@ -5,7 +5,7 @@ #include "etat.h" -#define SYSTICK_PER 360 // (360000 ticks équivaut à 5ms) +#define periode_tick_pwm 360 // (360000 ticks équivaut à 5ms) extern void timer_callback(void); @@ -26,11 +26,12 @@ int main(void) // config port PB0 pour être utilisé par TIM3-CH3 GPIO_Configure(GPIOB, 0, OUTPUT, ALT_PPULL); // config TIM3-CH3 en mode PWM - etat.resolution = PWM_Init_ff( TIM3, 3, SYSTICK_PER); + etat.resolution = PWM_Init_ff( TIM3, 3, periode_tick_pwm); etat.taille = LongueurSon; etat.periode_ticks = PeriodeSonMicroSec*72; etat.son = Son; + etat.position = 0; // initialisation du timer 4 // Periode_en_Tck doit fournir la durée entre interruptions, diff --git a/Src/signalCarre.s b/Src/signalCarre.s deleted file mode 100644 index b6c8504..0000000 --- a/Src/signalCarre.s +++ /dev/null @@ -1,48 +0,0 @@ -; ce programme est pour l'assembleur RealView (Keil) - thumb - area moncode, code, readonly - export timer_callback - extern etat -; -E_POS equ 0 -E_TAI equ 4 -E_SON equ 8 -E_RES equ 12 -E_PER equ 16 - -TIM3_CCR3 equ 0x4000043C ; adresse registre PWM - -timer_callback proc - - push{r4} - - ldr r1, =etat - ldr r2, [r1, #E_POS] - - ldr r3, [r1,#E_TAI] - cmp r2, r3 - beq silence - bne son -son ldr r4, [r1, #E_RES] - ldr r3, [r1, #E_SON] - ldrsh r3, [r3, r2,lsl #1] - - add r3, r3, lsl #16 - mul r3, r3, r4 - lsr r3, #16 - ;add r3, r3, r4 - ;lsl r3, #1 - - ldr r4, =TIM3_CCR3 - str r3, [r4] - - add r2,#1 - str r2,[r1, #E_POS] - -silence - - pop{r4} - bx lr - endp - end - \ No newline at end of file diff --git a/Src/wav_head.c b/Src/wav_head.c deleted file mode 100644 index 270e0cf..0000000 --- a/Src/wav_head.c +++ /dev/null @@ -1,173 +0,0 @@ -/* -------------------- WAV specific stuff --------------------------- */ - -/* wav est un cas de fichier RIFF. - * le fichier RIFF commence par "RIFF" (4 caracteres) suivi de la longueur - * du reste du fichier en long (4 bytes ordre Intel) - * puis on trouve "WAVE" suivi de chucks. - * chaque chuck commence par 4 caracteres (minuscules) suivis de la longueur - * du reste du chuck en long (4 bytes ordre Intel) - * le chuck "fmt " contient les parametres, sa longueur n'est pas tres fixe, - * il peut y avoir un chuck "fact" contenant le nombre de samples - * le chuck "data" contient les samples, - * tout autre doit etre ignore. - - header mini : - RIFF 4 ] - filesize 4 ] == 12 bytes de pre-header - WAVE 4 ] - fmt 4 le chuck fmt coute au moins 24 bytes en tout - chucksize 4 == 16 bytes utile - type 2 ] - chan 2 ] - freq 4 ] == 16 bytes - bps 4 ] - block 2 ] - resol 2 ] - data 4 - chucksize 4 == 8 bytes de post-header - -------------- - 44 au total - real filesize = chucksize + 44 - RIFF filesize = chucksize + 36 - - */ - -#include -#include -#include -#include -#include - -#include "wav_head.h" - - -unsigned long readlong( unsigned char *buf ) -{ -unsigned long l; -l = (unsigned long)buf[3] << 24 ; -l += (unsigned long)buf[2] << 16 ; -l += (unsigned long)buf[1] << 8 ; -l += buf[0]; -return(l); -} -unsigned int readshort( unsigned char *buf ) -{ -unsigned int s; -s = buf[0] + ( buf[1] << 8 ); -return(s); -} - -void WAVreadHeader( wavpars *s, int hand ) -{ -unsigned char buf[256]; unsigned long filesize, chucksize, factsize; -read( hand, buf, 4 ); -if ( strncmp( (char *)buf, "RIFF", 4 ) != 0 ) gasp("manque en-tete RIFF"); -read( hand, buf, 4 ); filesize = readlong( buf ); -read( hand, buf, 4 ); -if ( strncmp( (char *)buf, "WAVE", 4 ) != 0 ) gasp("manque en-tete WAVE"); - -read( hand, buf, 4 ); -if ( strncmp( (char *)buf, "fmt ", 4 ) != 0 ) gasp("manque chuck fmt"); -read( hand, buf, 4 ); chucksize = readlong( buf ); -if ( chucksize > (long)256 ) gasp("chuck fmt trop gros"); -read( hand, buf, (int)chucksize ); -if ( readshort(buf) != 1 ) gasp("fichier wave non PCM"); -s->chan = readshort( buf + 2 ); -s->freq = readlong( buf + 4 ); -s->bpsec = readlong( buf + 8 ); -s->block = readshort( buf + 12 ); -s->resol = readshort( buf + 14 ); -s->wavsize = 0L; -factsize = 0L; - -read( hand, buf, 4 ); -if ( strncmp( (char *)buf, "fact", 4 ) == 0 ) - { - read( hand, buf, 4 ); chucksize = readlong( buf ); - if ( chucksize > (long)256 ) gasp("chuck fmt trop gros"); - read( hand, buf, (int)chucksize ); - factsize = readlong( buf ); - read( hand, buf, 4 ); - } -if ( strncmp( (char *)buf, "data", 4 ) != 0 ) gasp("pas de chuck data"); -read( hand, buf, 4 ); chucksize = readlong( buf ); - -s->wavsize = chucksize / ( s->chan * ((s->resol)>>3) ); - -printf("%d canaux, %lu Hz, %lu bytes/s, %d bits\n", - s->chan, s->freq, s->bpsec, s->resol ); -printf("%lu echantillons selon data chuck\n", s->wavsize ); -if ( factsize != 0L ) - { - printf("%lu echantillons selon fact chuck\n", factsize ); - if ( s->wavsize != factsize ) - gasp("longueurs incoherentes"); - } -printf("fichier %lu bytes, chuck data %lu bytes\n", - filesize, chucksize ); - { - double durs, dmn, ds; int mn; - durs = s->wavsize; durs /= s->freq; - dmn = durs / 60.0; mn = (int)dmn; ds = durs - 60.0 * mn; - printf("duree %.3f s soit %d mn %.3f s\n", durs, mn, ds ); - } -} - -void writelong( unsigned char *buf, unsigned long l ) -{ -buf[0] = (unsigned char)l; l >>= 8; -buf[1] = (unsigned char)l; l >>= 8; -buf[2] = (unsigned char)l; l >>= 8; -buf[3] = (unsigned char)l; -} -void writeshort( unsigned char *buf, unsigned int s ) -{ -buf[0] = (unsigned char)s; s >>= 8; -buf[1] = (unsigned char)s; -} -void gulp() -{ gasp("erreur ecriture fichier"); -} - -void WAVwriteHeader( wavpars *d, int hand ) -{ -unsigned char buf[16]; long filesize, chucksize; - -d->bpsec = d->freq * d->chan * ((d->resol)>>3); -d->block = d->chan * ((d->resol)>>3); -chucksize = d->wavsize * d->chan * ((d->resol)>>3); -filesize = chucksize + 36; - -if ( write( hand, "RIFF", 4 ) != 4 ) gulp(); -writelong( buf, filesize ); -if ( write( hand, buf, 4 ) != 4 ) gulp(); - -if ( write( hand, "WAVE", 4 ) != 4 ) gulp(); -if ( write( hand, "fmt ", 4 ) != 4 ) gulp(); -writelong( buf, 16L ); -if ( write( hand, buf, 4 ) != 4 ) gulp(); - -writeshort( buf, 1 ); /* PCM type id */ -writeshort( buf + 2, d->chan ); -writelong( buf + 4, d->freq ); -writelong( buf + 8, d->bpsec ); -writeshort( buf + 12, d->block ); -writeshort( buf + 14, d->resol ); -if ( write( hand, buf, 16 ) != 16 ) gulp(); - -if ( write( hand, "data", 4 ) != 4 ) gulp(); -writelong( buf, chucksize ); -if ( write( hand, buf, 4 ) != 4 ) gulp(); -} - -/* --------------------------------------- traitement erreur fatale */ - -void gasp( char *fmt, ... ) -{ - char lbuf[2048]; - va_list argptr; - va_start( argptr, fmt ); - vsprintf( lbuf, fmt, argptr ); - va_end( argptr ); - printf("STOP : %s\n", lbuf ); exit(1); -} diff --git a/Src/wav_head.h b/Src/wav_head.h deleted file mode 100644 index 485f8bc..0000000 --- a/Src/wav_head.h +++ /dev/null @@ -1,18 +0,0 @@ -typedef struct { -int chan; -unsigned long freq; /* frequence d'echantillonnage */ -unsigned long bpsec; /* bytes par seconde */ -int block; -int resol; /* en bits */ -unsigned long wavsize; /* longueur en echantillons (par canal) */ -} wavpars; - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -void WAVreadHeader( wavpars *s, int hand ); - -void WAVwriteHeader( wavpars *d, int hand ); - -void gasp( char *fmt, ... ); /* traitement erreur fatale */