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.
Carte
Carte soudée :
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 mais mettre un délai entre 2 sons, 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;
}
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
const uint8_t audioBuffer[] PROGMEM = {
0xFF, 0x00, 0x80, 0x7F, 0x00, 0xFF, 0x7F, 0x80, 0x00, 0xFF, 0x80, 0x7F
};
Mais le son étant trop "bas" et de mauvaise qualité. Personne était capable de reconnaitre notre son.
Nous sommes donc passé sur un son plus "stridant" et "aigu". Pour avoir un son plus facilement reconnaissable.
Le sample étant trouvé ici sous format wav comme décrit plus haut:
https://samplefocus.com/samples/8-bit-kit-beep
Après l'avoir converti en 8 bits low définition (gain de place) et utilisé xxd nous avons récupérer le contenu du fichier sous format hexadécimal.
Nous l'avons stocké dans un tableau, nous le parcourons allant de 0 à la taille du tableau, et, à chaque tour de boucle, nous donnons au port B (speaker) la valeur courant du bit du tableau. Avec un délai entre chaque pour obtenir le son voulu. for (uint16_t i = 0; i < sizeof(audioBuffer); i++) {
uint8_t sample = pgm_read_byte(&audioBuffer[i]);
PORTB = sample;
_delay_us(60);
}
#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 = {
0x52, 0x49, 0x46, 0x46, 0x0a, 0x04, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45,
0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
0x40, 0x1f, 0x00, 0x00, 0x40, 0x1f, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00,
0x64, 0x61, 0x74, 0x61, 0xe6, 0x03, 0x00, 0x00, 0x7c, 0x6b, 0x51, 0x3d,
0x25, 0x16, 0x0d, 0x07, 0x0a, 0x00, 0xc1, 0xff, 0xf1, 0xff, 0xf5, 0xfe,
0xf7, 0xfd, 0xf9, 0xfc, 0xf9, 0xfb, 0xfa, 0xfa, 0xfb, 0xfa, 0xfb, 0xfa,
0xfb, 0xfa, 0xfa, 0xfb, 0xf9, 0xfb, 0x33, 0x00, 0x0e, 0x00, 0x0b, 0x00,
0x0b, 0x03, 0xd6, 0xff, 0xf6, 0xfe, 0xf7, 0xfd, 0xf7, 0xfa, 0x27, 0x00,
0x0a, 0x03, 0x08, 0x03, 0x07, 0x08, 0xdb, 0xff, 0xf6, 0xfe, 0xf8, 0xfd,
0xf8, 0xf7, 0x22, 0x00, 0x09, 0x03, 0x08, 0x04, 0x07, 0x0b, 0xe0, 0xff,
0xf7, 0xfc, 0xf9, 0xfb, 0xfa, 0xf2, 0x1d, 0x00, 0x08, 0x04, 0x07, 0x05,
0x05, 0x11, 0xe6, 0xfe, 0xf9, 0xfb, 0xfa, 0xfa, 0xfd, 0xec, 0x17, 0x03,
0x07, 0x05, 0x05, 0x07, 0x02, 0x18, 0xed, 0xfc, 0xfa, 0xfa, 0xfb, 0xf9,
0xff, 0xe5, 0x10, 0x05, 0x05, 0x07, 0x04, 0x09, 0x00, 0x1f, 0xf3, 0xfa,
0xfc, 0xf9, 0xfd, 0xf7, 0xff, 0xdf, 0x0b, 0x07, 0x04, 0x07, 0x04, 0x09,
0x00, 0x22, 0xf8, 0xf7, 0xfe, 0xf7, 0xff, 0xf5, 0xff, 0xd9, 0x09, 0x07,
0x05, 0x06, 0x05, 0x06, 0x05, 0x07, 0x04, 0x07, 0x04, 0x08, 0x02, 0x0b,
0x00, 0x2d, 0xfd, 0xf6, 0xfe, 0xf7, 0xfe, 0xf5, 0xff, 0xcf, 0x00, 0x0c,
0x00, 0x0b, 0x00, 0x0d, 0x00, 0x36, 0xff, 0xf5, 0xff, 0xf5, 0xff, 0xf3,
0xff, 0xc6, 0x00, 0x0d, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x3e, 0xff, 0xf2,
0xff, 0xf4, 0xff, 0xf1, 0xff, 0xbe, 0x00, 0x0e, 0x00, 0x0c, 0x00, 0x0f,
0x00, 0x45, 0xff, 0xf1, 0xff, 0xf4, 0xff, 0xf1, 0xff, 0xb9, 0x00, 0x0f,
0x00, 0x0d, 0x00, 0x10, 0x00, 0x4b, 0xff, 0xf1, 0xff, 0xf3, 0xff, 0xf0,
0xff, 0xb0, 0x00, 0x10, 0x00, 0x0d, 0x00, 0x10, 0x00, 0x55, 0xff, 0xf0,
0xff, 0xf2, 0xff, 0xef, 0xff, 0xa6, 0x00, 0x11, 0x00, 0x0e, 0x00, 0x11,
0x00, 0x5e, 0xff, 0xef, 0xff, 0xf2, 0xff, 0xee, 0xff, 0x9d, 0x00, 0x12,
0x00, 0x0f, 0x00, 0x12, 0x00, 0x68, 0xff, 0xee, 0xff, 0xf1, 0xff, 0xee,
0xff, 0x95, 0x00, 0x12, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x6e, 0xff, 0xee,
0xff, 0xf1, 0xff, 0xee, 0xff, 0x8f, 0x00, 0x13, 0x00, 0x0f, 0x00, 0x13,
0x00, 0x76, 0xff, 0xed, 0xff, 0xf0, 0xff, 0xec, 0xff, 0x83, 0x00, 0x10,
0x00, 0x0a, 0x02, 0x08, 0x03, 0x08, 0x04, 0x08, 0x03, 0x08, 0x02, 0x0b,
0x00, 0x44, 0x8b, 0x7a, 0x84, 0x7d, 0x82, 0x7e, 0x82, 0x7f, 0x81, 0x7f,
0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80
};
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) {
for (uint16_t i = 0; i < sizeof(audioBuffer); i++) {
uint8_t sample = pgm_read_byte(&audioBuffer[i]);
PORTB = sample;
_delay_us(60);
}
_delay_ms(1000);
}
return 0;
}
Prog USB
Le programme qui va sur le microcontrôleur
FAIRE PARLER LE HP EN MEME TEMPS QUE LA LED
Nous allons juste reprendres les 2 parties des codes écrits auparavant.
Code 1 : le speaker qui parle (cf juste au dessus)
Code 2 : la led qui clignotePORTD |= (1 << LED);
_delay_ms(5);
PORTD &= ~(1 << LED);
_delay_ms(5);
#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 = {
0x52, 0x49, 0x46, 0x46, 0x0a, 0x04, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45,
... LE RESTE DE L'HEXA
};
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) {
PORTD &= ~(1 << LED);
for (uint16_t i = 0; i < sizeof(audioBuffer); i++) {
uint8_t sample = pgm_read_byte(&audioBuffer[i]);
PORTB = sample;
_delay_us(55);
}
PORTD |= (1 << LED);
_delay_ms(1000);
}
return 0;
}
FAIRE PARLER LE HP ET LA LED EN MEME TEMPS QU'UN APPUI CLAVIER
Prog PC
Le programme qui tourne sur le pc