I2L 2022 Groupe6
Proposition de système
Nous voudrions équiper la carte d'un port USB, d'une horloge, d'une LED, d'un bouton et d'un haut-parleur. Le but final serait de, lors d'un appui bouton et/ou CapsLock (à définir ensemble), de faire un son et un allumage de la LED.
Contre-proposition
L'idée est bien de refléter l'ensemble de l'état des touches "verrous" du clavier du PC. A chaque changement d'état de ces touches vous associerez un signal lumineux avec les 3 LED multicolores et surtout un signal sonore. Vous êtes tenus de produire des sons et pas seulement des notes. Pour cela vous devrez réussir à stocker (en mémoire flash) des échantillons sonores et à les reproduire sur votre haut-parleur.
Fichiers
Vous utiliserez le même circuit imprimé que le groupe 5.
Installation
Installation des dépendances :
apt install gcc-avr avr-libc dfu-programmer
Passer du fichier source au fichier exécutable :
Compil : avr-gcc -mmcu=atmega16u2 -DF_CPU=16000000UL -c -Wall -I. -Os main.c -o main.o
Edition des liens (exe) : avr-gcc -mmcu=atmega16u2 -g -lm -Wl,--gc-sections -o main.elf main.o
Transformer le code source en fichiers utilisable pour la carte
avr-objcopy -j .text -j .data -O ihex main.elf main.hex
dfu-programmer atmega16u2 erase
dfu-programmer atmega16u2 flash time.hex
dfu-programmer atmega16u2 reset
Programmation
MAKEFILE
AVR = avr-gcc
AVR_HEX = avr-objcopy
TARGET = atmega16u2
DFU = dfu-programmer
CFLAGS = -mmcu=atmega16u2 -DF_CPU=16000000UL -Wall -I. -Os
CLINKS = -mmcu=atmega16u2 -g -lm -Wl,--gc-sections
CHEXS = -j .text -j .data -O
SRC = main.c
OBJ = main.o
ELF = main.elf
HEX = main.hex
push: clean compile link hex erase flash reset
compile:
$(AVR) $(CFLAGS) -c $(SRC) -o $(OBJ)
link:
$(AVR) $(CLINKS) -o $(ELF) $(OBJ)
hex:
$(AVR_HEX) $(CHEXS) ihex $(ELF) $(HEX)
erase:
$(DFU) $(TARGET) erase
flash:
$(DFU) $(TARGET) flash $(HEX)
reset:
$(DFU) $(TARGET) reset
clean:
rm -f $(OBJ) $(EXEC)
Prog SE
LED
Faire clignoter une led
#include <avr/io.h>
#include <util/delay.h>
#define LED 0
#define BUTTON 2
int main(void){
DDRD |= (1 << LED); // Sortie pour la LED
PORTD &= ~(1 << LED); // Configuration de la résistance de tirage
while(1) {
PORTD |= (1 << LED);
_delay_ms(5);
PORTD &= ~(1 << LED);
_delay_ms(5);
}
}
Boutons
Faire clignoter une led en fonction du bouton
#include <avr/io.h>
#include <util/delay.h>
#define LED 0
#define BUTTON 2
int main(void){
CLKSEL0 = 0b00010101;
CLKSEL1 = 0b00001111;
CLKPR = 0b10000000;
CLKPR = 0;
DDRD |= (1 << LED);
PORTD &= ~(1 << LED);
DDRC &= ~(1 << BUTTON);
PORTC |= (1 << BUTTON);
while(1) {
if (!(PINC & (1 << BUTTON)))
{
PORTD |= (1 << LED);
_delay_ms(5);
PORTD &= ~(1 << LED);
_delay_ms(5);
}
}
}
HP
Faire parler le HP
Alimenter le HP et lui fournir une fréquence fixe, pour débuter :
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#define TONE_FREQUENCY 1000 // 1kHz
#define TONE_DURATION_MS 1000 // 1 second
#define SAMPLE_RATE 8000
#define BUFFER_SIZE SAMPLE_RATE / (1000 / TONE_DURATION_MS)
#define LED 0
#define BUTTON 2
#define SPEAKER 7
int main(void){
CLKSEL0 = 0b00010101;
CLKSEL1 = 0b00001111;
CLKPR = 0b10000000;
CLKPR = 0;
TCCR1A = (1 << COM1A0);
TCCR1B = (1 << WGM12) | (1 << CS10);
OCR1A = F_CPU / (2 * SAMPLE_RATE) - 1;
DDRD |= (1 << LED);
PORTD &= ~(1 << LED);
DDRB |= (1 << SPEAKER);
PORTB &= ~(1 << SPEAKER);
while(1) {
uint16_t i;
for (i = 0; i < BUFFER_SIZE; i++) {
PORTB ^= (1 << SPEAKER);
_delay_us(1000000UL / (2 * TONE_FREQUENCY));
}
PORTB &= ~(1 << SPEAKER);
}
return 0;
}
Fournir un son de test bufferAudio PROGMEM codé en 8bit fourni au HP :
1) Conversion du fichier aac ou mp3 en fichier codé sous 8bit -> sortie du fichier wav via https://g711.org/
Low Definition 8-bit WAV (8Khz, Mono, 8-Bit PCM)
2) Passer du 8-bit WAV en hexadécimal -> utilisation de la commande linux xxd -i nomDuFichierAudio
A partir de maintenant, nous avons le contenu du fichier audio sous forme hexadécimal et pouvons le stocker et l'utiliser en c
EXEMPLE :
const uint8_t audioBuffer[] PROGMEM = {
0xFF, 0x00, 0x80, 0x7F, 0x00, 0xFF, 0x7F, 0x80, 0x00, 0xFF, 0x80, 0x7F
};
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#define TONE_FREQUENCY 1000 // 1kHz
#define TONE_DURATION_MS 1000 // 1 second
#define SAMPLE_RATE 8000
#define BUFFER_SIZE SAMPLE_RATE / (1000 / TONE_DURATION_MS)
#define LED 0
#define BUTTON 2
#define SPEAKER 7
const uint8_t audioBuffer[] PROGMEM = {
0xFF, 0x00, 0x80, 0x7F, 0x00, 0xFF, 0x7F, 0x80, 0x00, 0xFF, 0x80, 0x7F
};
int main(void){
CLKSEL0 = 0b00010101;
CLKSEL1 = 0b00001111;
CLKPR = 0b10000000;
CLKPR = 0;
TCCR1A = (1 << COM1A0);
TCCR1B = (1 << WGM12) | (1 << CS10);
OCR1A = F_CPU / (2 * SAMPLE_RATE) - 1;
DDRD |= (1 << LED);
PORTD &= ~(1 << LED);
DDRB |= (1 << SPEAKER);
PORTB &= ~(1 << SPEAKER);
while(1) {
uint16_t i;
for (i = 0; i < BUFFER_SIZE; i++) {
PORTB ^= (1 << SPEAKER);
_delay_us(1000000UL / (2 * TONE_FREQUENCY));
}
PORTB &= ~(1 << SPEAKER);
}
return 0;
}
Prog USB
Le programme qui va sur le microcontrôleur
Prog PC
Le programme qui tourne sur le pc