3 of 8 bit
parent
1d5191aafd
commit
cef4f78b3c
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Soundcode von: Michael Smith <michael@hurts.ca> - http://www.arduino.cc/playground/Code/PCMAudio
|
||||
* CapSense: http://www.arduino.cc/playground/Main/CapSense
|
||||
* basierend auf code von Alex Wenger 2009 ("Arduino Physical Computing ...")
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/delay.h>
|
||||
|
||||
// Audioausgabe
|
||||
#define SAMPLE_RATE 8000
|
||||
|
||||
// Auf welchem PIN soll Audio ausgegeben werden? (nicht Ändern!!!)
|
||||
int speakerPin = 11;
|
||||
|
||||
const unsigned char sintab[] PROGMEM = {
|
||||
0x01,0x01,0x01,0x01,0x02,0x03,0x05,0x07,
|
||||
0x09,0x0c,0x0f,0x12,0x15,0x19,0x1c,0x21,
|
||||
0x25,0x29,0x2e,0x33,0x38,0x3d,0x43,0x48,
|
||||
0x4e,0x54,0x5a,0x60,0x66,0x6c,0x73,0x79,
|
||||
0x7f,0x85,0x8b,0x92,0x98,0x9e,0xa4,0xaa,
|
||||
0xb0,0xb6,0xbb,0xc1,0xc6,0xcb,0xd0,0xd5,
|
||||
0xd9,0xdd,0xe2,0xe5,0xe9,0xec,0xef,0xf2,
|
||||
0xf5,0xf7,0xf9,0xfb,0xfc,0xfd,0xfe,0xfe,
|
||||
0xfe,0xfe,0xfe,0xfd,0xfc,0xfb,0xf9,0xf7,
|
||||
0xf5,0xf2,0xef,0xec,0xe9,0xe5,0xe2,0xdd,
|
||||
0xd9,0xd5,0xd0,0xcb,0xc6,0xc1,0xbb,0xb6,
|
||||
0xb0,0xaa,0xa4,0x9e,0x98,0x92,0x8b,0x85,
|
||||
0x7f,0x79,0x73,0x6c,0x66,0x60,0x5a,0x54,
|
||||
0x4e,0x48,0x43,0x3d,0x38,0x33,0x2e,0x29,
|
||||
0x25,0x21,0x1c,0x19,0x15,0x12,0x0f,0x0c,
|
||||
0x09,0x07,0x05,0x03,0x02,0x01,0x01,0x01
|
||||
};
|
||||
|
||||
|
||||
volatile uint16_t sample1; // welches ist das nächste Sample aus der Sinustabelle
|
||||
// die oberen 7 bit zeigen in die Tabelle, die restlichen
|
||||
// bits sind kommastellen
|
||||
volatile uint16_t sample2;
|
||||
volatile uint16_t sample3;
|
||||
|
||||
uint16_t vol; // aktuelle Lautstärke
|
||||
volatile uint16_t set_vol; // gewuenschte Lautstärke
|
||||
volatile uint16_t tone1; // Tonhöhe in "Inkrementiereinheiten"
|
||||
volatile uint16_t tone2; // Tonhöhe in "Inkrementiereinheiten"
|
||||
volatile uint16_t tone3; // Tonhöhe in "Inkrementiereinheiten"
|
||||
|
||||
|
||||
// Interruptroutine, diese wird 8000 mal pro Sekunde aufgerufen und berechnet den nächsten
|
||||
// Wert für die Tonausgabe
|
||||
ISR(TIMER1_COMPA_vect) {
|
||||
static int timer1counter; // Zähler um Lautstärkeänderung langsamer zu machen
|
||||
int wert;
|
||||
|
||||
// Wert an der Stelle sample1/512 aus der sinus-Tabelle lesen
|
||||
wert = pgm_read_byte(&sintab[(sample1 >> 9)])+
|
||||
pgm_read_byte(&sintab[(sample2 >> 9)])+
|
||||
pgm_read_byte(&sintab[(sample3 >> 9)]);
|
||||
// Wert mit der aktuellen Lautstärke multiplizieren
|
||||
wert = (wert * vol) / 256;
|
||||
// PWM Hardware anweisen ab jetzt diesen Wert auszugeben
|
||||
OCR2A = wert;
|
||||
|
||||
// nächstes Sample in der Sinustabelle abhängig vom gewünschten
|
||||
// Ton auswählen.
|
||||
sample1 += tone1;
|
||||
sample2 += tone2;
|
||||
sample3 += tone3;
|
||||
|
||||
// Lautstärke anpassen wen gewünscht (nur alle 50 Interrupts, damit
|
||||
// es schön langsam passiert.
|
||||
timer1counter++;
|
||||
if (timer1counter > 50)
|
||||
{
|
||||
timer1counter = 0;
|
||||
if (vol < set_vol) vol++;
|
||||
if (vol > set_vol) vol--;
|
||||
}
|
||||
}
|
||||
|
||||
void startPlayback()
|
||||
{
|
||||
pinMode(speakerPin, OUTPUT);
|
||||
|
||||
// Initialisiere den Timer 2 für die schnelle PWM zur
|
||||
// Soundausgabe auf Pin 11
|
||||
|
||||
// Verwende den internen Takt (Datenblatt Seite 160)
|
||||
ASSR &= ~(_BV(EXCLK) | _BV(AS2));
|
||||
|
||||
// Fast PWM mode (Seite 157)
|
||||
TCCR2A |= _BV(WGM21) | _BV(WGM20);
|
||||
TCCR2B &= ~_BV(WGM22);
|
||||
|
||||
// Wähle die nicht invertierende PWM für pin OC2A und OC2B
|
||||
// Am Arduino ist das Pin 11 und 3
|
||||
TCCR2A = (TCCR2A | _BV(COM2A1) | _BV(COM2B1));
|
||||
|
||||
// Keine Vorteiler / wir wollen es schnell! (Seite 158)
|
||||
TCCR2B = (TCCR2B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
|
||||
|
||||
// Start Wert = 0, sonst gibt es ein hässliches Ploppgeräusch
|
||||
OCR2A = 0;
|
||||
OCR2B = 0;
|
||||
|
||||
// Initialisiere Timer 1 für 8000 Interrupts/Sekunde
|
||||
cli();
|
||||
|
||||
// Set CTC mode (Clear Timer on Compare Match) (Seite 133)
|
||||
TCCR1B = (TCCR1B & ~_BV(WGM13)) | _BV(WGM12);
|
||||
TCCR1A = TCCR1A & ~(_BV(WGM11) | _BV(WGM10));
|
||||
|
||||
// Kein Vorteiler (Seite 134)
|
||||
TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
|
||||
|
||||
// Gewünschte Frequenz = 8000kHz
|
||||
OCR1A = F_CPU / SAMPLE_RATE; // 16e6 / 8000 = 2000
|
||||
|
||||
// Aktiviere den Interrupt für TCNT1 == OCR1A (Seite 136)
|
||||
TIMSK1 |= _BV(OCIE1A);
|
||||
|
||||
// Startwerte
|
||||
sample1 = 0;
|
||||
sample2 = 0;
|
||||
sample3 = 0;
|
||||
|
||||
// Global Interrupts wieder einschalten.
|
||||
sei();
|
||||
}
|
||||
|
||||
// Aendert Ton und Lautstärke
|
||||
// ton (50-4000Hz)
|
||||
// volume (0-256);
|
||||
void SetFreq(int ton1,int ton2, int ton3, int volume)
|
||||
{
|
||||
tone1 = (128ul*512ul*ton1)/8000;
|
||||
tone2 = (128ul*512ul*ton2)/8000;
|
||||
tone3 = (128ul*512ul*ton3)/8000;
|
||||
set_vol = volume;
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
startPlayback();
|
||||
}
|
||||
|
||||
#include "pitches.h"
|
||||
void loop()
|
||||
{
|
||||
for(int counter = 0; counter<256; counter++) {
|
||||
SetFreq((counter & _BV(0))?(NOTE_C4):0,
|
||||
(counter & _BV(1))?(NOTE_A3):0,
|
||||
(counter & _BV(2))?(NOTE_F3):0,
|
||||
80);
|
||||
if ((counter % 8) != 0) {
|
||||
_delay_ms(500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,95 @@
|
||||
/*************************************************
|
||||
* Public Constants
|
||||
*************************************************/
|
||||
|
||||
#define NOTE_B0 31
|
||||
#define NOTE_C1 33
|
||||
#define NOTE_CS1 35
|
||||
#define NOTE_D1 37
|
||||
#define NOTE_DS1 39
|
||||
#define NOTE_E1 41
|
||||
#define NOTE_F1 44
|
||||
#define NOTE_FS1 46
|
||||
#define NOTE_G1 49
|
||||
#define NOTE_GS1 52
|
||||
#define NOTE_A1 55
|
||||
#define NOTE_AS1 58
|
||||
#define NOTE_B1 62
|
||||
#define NOTE_C2 65
|
||||
#define NOTE_CS2 69
|
||||
#define NOTE_D2 73
|
||||
#define NOTE_DS2 78
|
||||
#define NOTE_E2 82
|
||||
#define NOTE_F2 87
|
||||
#define NOTE_FS2 93
|
||||
#define NOTE_G2 98
|
||||
#define NOTE_GS2 104
|
||||
#define NOTE_A2 110
|
||||
#define NOTE_AS2 117
|
||||
#define NOTE_B2 123
|
||||
#define NOTE_C3 131
|
||||
#define NOTE_CS3 139
|
||||
#define NOTE_D3 147
|
||||
#define NOTE_DS3 156
|
||||
#define NOTE_E3 165
|
||||
#define NOTE_F3 175
|
||||
#define NOTE_FS3 185
|
||||
#define NOTE_G3 196
|
||||
#define NOTE_GS3 208
|
||||
#define NOTE_A3 220
|
||||
#define NOTE_AS3 233
|
||||
#define NOTE_B3 247
|
||||
#define NOTE_C4 262
|
||||
#define NOTE_CS4 277
|
||||
#define NOTE_D4 294
|
||||
#define NOTE_DS4 311
|
||||
#define NOTE_E4 330
|
||||
#define NOTE_F4 349
|
||||
#define NOTE_FS4 370
|
||||
#define NOTE_G4 392
|
||||
#define NOTE_GS4 415
|
||||
#define NOTE_A4 440
|
||||
#define NOTE_AS4 466
|
||||
#define NOTE_B4 494
|
||||
#define NOTE_C5 523
|
||||
#define NOTE_CS5 554
|
||||
#define NOTE_D5 587
|
||||
#define NOTE_DS5 622
|
||||
#define NOTE_E5 659
|
||||
#define NOTE_F5 698
|
||||
#define NOTE_FS5 740
|
||||
#define NOTE_G5 784
|
||||
#define NOTE_GS5 831
|
||||
#define NOTE_A5 880
|
||||
#define NOTE_AS5 932
|
||||
#define NOTE_B5 988
|
||||
#define NOTE_C6 1047
|
||||
#define NOTE_CS6 1109
|
||||
#define NOTE_D6 1175
|
||||
#define NOTE_DS6 1245
|
||||
#define NOTE_E6 1319
|
||||
#define NOTE_F6 1397
|
||||
#define NOTE_FS6 1480
|
||||
#define NOTE_G6 1568
|
||||
#define NOTE_GS6 1661
|
||||
#define NOTE_A6 1760
|
||||
#define NOTE_AS6 1865
|
||||
#define NOTE_B6 1976
|
||||
#define NOTE_C7 2093
|
||||
#define NOTE_CS7 2217
|
||||
#define NOTE_D7 2349
|
||||
#define NOTE_DS7 2489
|
||||
#define NOTE_E7 2637
|
||||
#define NOTE_F7 2794
|
||||
#define NOTE_FS7 2960
|
||||
#define NOTE_G7 3136
|
||||
#define NOTE_GS7 3322
|
||||
#define NOTE_A7 3520
|
||||
#define NOTE_AS7 3729
|
||||
#define NOTE_B7 3951
|
||||
#define NOTE_C8 4186
|
||||
#define NOTE_CS8 4435
|
||||
#define NOTE_D8 4699
|
||||
#define NOTE_DS8 4978
|
||||
|
||||
|
Reference in New Issue