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

/* Kode für mfv2d: 425-Hz-Messung mittels Analogvergleicher an PB1 = AC- = Pin6
	und Nulldurchgangs-Abstandsmessung.
	Genauso wie beim CLIP-Empfang, nur mit freigegebenen Interrupts
	und (damit) ohne ISR. Und das andere Pin.
	Erfordert Schutzwiderstand an nsi+nsa.
	Einzige exportierte Funktion ist „bool mess425()“,
	die bis zum Watchdog-Interrupt (Flags&0x80) = 16 ms arbeiten darf.
 220411	erstellt
*/

#include <avr/io.h>
#include <avr/sleep.h>
typedef unsigned char byte;
typedef unsigned short word;
constexpr char LOG2(unsigned v) {return 15-__builtin_clz(v);}
constexpr char CLOG2 = LOG2(F_CPU/1000000);
#define Flags	GPIOR0	// Bits für NSK() u.a.
//extern void eechange(byte);	// Debug

// Wahlweise kann (0) PB0 fixiert und PB1 detektiert werden
// oder (1) PB1 fixiert und PB0 detektiert werden.
#define FIX 0
// (0):	+ Keine Störung beim Sprechen
//	- Langer Einschwingvorgang
//	+ Funktioniert besser: Weniger Störungen festgestellt
//	- Widerstand 10 kΩ zur Wählscheibe erforderlich
// (1):	+ Funktion wie CLIP-Empfang
//	+ Kurzes Einschwingen
//	- Kann Sprechen stören (hörbare Amplitudenmodulation)
//	- Funktioniert irgendwie schlechter, DC-Versatz?

bool mess425() {	// Messung 425 Hz mit Analogvergleicher
 if (!(PINB&1)) return false;	// Wählscheibe blockiert Empfang (zurzeit!)
 if (DDRB&2) return false;	// Tonausgabe läuft: Messung sinnlos + Timer0 blockiert
 if (PB5DEBUG&3) DDRB|= 0x20;
// Hier steht als Zeitbasis ein freier Timer0 zur Verfügung
 TCCR0B = 0x03;	// Vorteiler 64
 ACSR   = 0x03;	// Nur steigende Flanke erfassen, unterdrückt tieffrequente Überlagerungen
 PORTB |= 0x02;
 DDRB  |= 1<<FIX;
 byte zc=0xFF, tic=0, zcok=0;
 ACSR  |= 0x10;
 do{
  if (PB5DEBUG&2) {
   if (ACSR&0x20) PORTB|=0x20;
   else PORTB&=~0x20;
  }
  if (ACSR&0x10) {	// Interrupt?
// Das Signal hat an PB0 oder PB1 eine Amplitude von 150 mVss
// und ist von nadelartigen Störungen überlagert.
// Deshalb zu kurze Abstände ausblenden.
   byte dt=TCNT0-tic;
   constexpr byte EL=F_CPU/(1<<CLOG2)/64/3400;	// Etwas höheres als 3,4 kHz kommt nicht; EL = 4,6
   if (dt>=EL && ACSR&0x20) {	// Lang genug und immer noch High?  Low ignorieren, war Nadelimpuls
    if (PB5DEBUG&1) PINB|= 0x20;	// Toggeln
    tic+=dt;
    if (++zc) {		// Beim nicht-ersten Nulldurchgang Zeit bewerten
     constexpr byte DT=F_CPU/(1<<CLOG2)/64/425;	// Gesuchte Frequenz; SA = 36,8
     constexpr byte DW=0;
     if (DT-DW<=dt && dt<=DT+DW+1) {
      ++zcok;
      if (PB5DEBUG&1) PORTB|= 0x20;
     }else if (PB5DEBUG&1) PORTB&=~0x20;
    }
   }
   ACSR |= 0x10;		// Interruptflag (jetzt erst!) löschen
  }
 }while(!(Flags&0x80) && PINB&1);
 DDRB  &=~(1<<FIX);
 PORTB &=~0x02;
 ACSR   = 0x80;
 TCCR0B = 0;
 if (PB5DEBUG&3) {
  DDRB &=~0x20;
  PORTB|= 0x20;
 }
 return zc>=4 && zcok>=zc-1;
}
Detected encoding: UTF-80