Source file: /~heha/basteln/Haus/Telefon/Impulswahl→DTMF/mfv.zip/mfv2d/dtmf.cpp

#ifdef __AVR_ATtiny85__
#include <avr/io.h>
#include <avr/pgmspace.h>
typedef unsigned char byte;
typedef unsigned short word;
#define NOINIT __attribute__((section(".noinit")))
#define SINTAB __attribute__((section(".sintab")))

// Sinustabelle, Amplitude 127
extern const struct Sinus127{
 char a[256] {};
 constexpr Sinus127() {
  constexpr float PI=__builtin_atan(1)*4;
  for (size_t x=0; x<256; x++)
   a[x]=__builtin_round(__builtin_sin(x*PI/128)*127);
 }
}sinus127 SINTAB;
const Sinus127 sinus127 SINTAB;

// Fensterfunktion für 256 Samples: Bei 8 MHz und 9,6 kSa/s sind das 26,6 ms
// Ein langes Fenster wird benötigt,
// um die Frequenzdifferenzen von nur 80 Hz klar zu unterscheiden.
extern const struct Fenster127{
 char a[256] {};
 constexpr Fenster127() {
  constexpr float PI=__builtin_atan(1)*4;
  for (size_t x=0; x<256; x++) {
   auto si=__builtin_sin(x*PI/256);
   a[x]=__builtin_round(si*si*127);
  }
 }
}fenster127 SINTAB;
const Fenster127 fenster127 SINTAB;

constexpr word ADCDIV = 64*13;	// 832 Takte pro Sample

// DftScan-Struktur, jede Zahl 16 Bit
// * DC-Summe (alles nach Begrenzung und Fensterung)
// * Betragssumme
// * Für jede Suchfrequenz (maximal 7):
//   * Addierwerte entsprechend Suchfrequenz (Konstanten)
//   * Phasenwerte (variabel)
//   * Addierwerte Sinus (Imaginärteil)
//   * Addierwerte Kosinus (Realteil) => Wird zum Betrag der komplexen Zahl
extern struct DftScan{	// sizeof = 4 + 7×8 = 60 Byte RAM
 struct{
  private: word sum; int dcs; public:
  int dc() const {return dcs;}
  word volt() const {return sum;}	// Gesamtspannung
 }sum;
 struct{
  word add;
  private: word pha; int im,re; public:
  word volt() const {return re;}	// Spektralspannung
 }f[7];
 void operator()(byte fsize,byte angleadd=1,int mean=0x380);
}dftScan NOINIT;

DftScan dftScan NOINIT;

constexpr word FREQ(float x) {return x*65536*ADCDIV/F_CPU+0.5;}

byte dtmfScan() {
// DDS-Inkremente = Additionswerte auf Phasenwert alle F_CPU/T0DIV
 static PROGMEM const word FSearch[8] = {
  FREQ( 697),
  FREQ( 770),
  FREQ( 852),
  FREQ( 941),
  FREQ(1209),
  FREQ(1336),
  FREQ(1477),
  FREQ(1633),
 };
 for (byte i=0; i<7; i++) dftScan.f[i].add=pgm_read_word(FSearch+i);
 ADCSRA=0xF6;		// Start; ADC-Taktteiler stets 64
 dftScan(7,F_CPU>=8000000?1:2);
 byte r=0;
 for (byte i=0, m=1; i<7; i++,m<<=1) if (dftScan.f[i].volt()>1000) r|=m;
 if (dftScan.sum.volt()>1000) r|=0x80;	// TODO: Schwellen festlegen
 return r;				// TODO: Auswerten (2 Linien)
}

byte freiScan() {
 dftScan.f[0].add=FREQ(425)/2;
 ADCSRA=0xF5;		// Start; ADC-Taktteiler hier 32
 dftScan(1);
 byte r=0;
 if (dftScan.f[0].volt()>1000) r|=0x01;	// TODO: Schwellen festlegen
 if (dftScan.sum.volt()>1000) r|=0x80;
 return r;
}
#endif
Detected encoding: UTF-80