// CLIP für Analogvergleicher und Timer0
// Projekt Rufnummern-Anzeige
#include "ra.h"
static void terminate() {
#ifdef TIMSK0
TIMSK0&=~0x06;
#else
TIMSK&=~0x18;
#endif
if (stat>=4 && cnt) stat=0xFF;
else stat=0;
}
// Zählerwert Timer0 für 1200 Hz
#define T F_CPU/64/1200
// Flanke an Analogvergleicher
ISR(ANA_COMP_vect) {
byte t=ACSRA;
byte e=GPIOR0;
if (!((t^e)&0x20)) return; // Ohne Pegelwechsel an ACO ignorieren
PINB|=4;
t=TCNT0L-last;
if (stat) {
if (t<T/8) return; // Zu kurz: Ignorieren
GPIOR0=e^0x20; // Nulldurchgang akzeptieren
dif1=diff;
diff=t;
}
last+=t;
OCR0B=t+250; // Zeitüberschreitung (zu tiefe Frequenz) feststellen lassen
if (!stat) {
#ifdef TIMSK0
TIFR0=0x04;
TIMSK0|=0x04;
#else
TIFR=0x08;
TIMSK|=0x08; // OCR0B aktivieren (für Timeout)
#endif
}
switch (stat) {
case 0: // Initialisierung: Erste Flanke
cnt=akku=det=stat++;
break;
case 1: { // Frequenzsuche: Trennschwelle zwischen hoch und tief
add(akku,diff);
adc0(det); // 16-Bit-Zähler
add(cnt,1);
adc0(stat); // 256 Flanken messen
}break;
case 2: // Sicherstellen dass diese Trennschwelle auch stimmt
#if 0
if (byte(det-32)<diff && diff<byte(det+32)) {
add(cnt,16);
adc0(stat); // erfolgreich
}else{
cnt=0;
--stat; // weitersuchen
}break;
#else
++stat;
#endif
case 3: // Suche dauerhaft tiefe Frequenz gegenüber Trennschwelle
if (diff>=det) {
add(cnt,16);
adc0(stat);
}else cnt=0; // Frequenz zu hoch // einige Nulldurchgänge lang
break;
case 4: // Suche nach Startbit
if (diff<det && dif1<det) {
++stat;
t+=T-20-dif1-diff; // ausprobiert: Zeit des „wahren“ Startbits
OCR0A=t; // Das „wahre Startbit“ kommt zu jener Zeit, wird ignoriert
#ifdef TIMSK0
TIFR0=0x02; // Anhängigen Interrupt löschen
TIMSK0|=0x02; // Beide Compare-Interrupts freigeben
#else
TIFR=0x10;
TIMSK|=0x10; // OCR0A aktivieren
#endif
}break;
}
}
#define TOL 0
static bool bit() {
#if TOL==100
return diff+dif1>=det+det;
#elif TOL
return diff>det+TOL || diff>det-TOL && dif1>=det;
#else
return diff>=det;
#endif
}
// Bitzeit, stat = 5..13
ISR(TIMER0_COMPA_vect) {
akku>>=1;
if (bit()) {
akku|=0x80; // Tiefe Frequenz = 1
}
sei(); // Ab hier darf der Pegelwechsel-Interrupt einschlagen
switch (++stat) {
#if 0
case 15: stat=5; OCR0A+=F_CPU/64/1200+3; break;
#else
case 15: { // Rahmenfehler detektieren
if (!(akku&0x80) || cnt>=2 && cnt==clip.data[1]+3) terminate();
stat=4; // Startbit suchen lassen
#ifdef TIMSK0
TIMSK0&=~0x02;
#else
TIMSK&=~0x10;// OCR0A deaktivieren
#endif
}break;
#endif
case 14: switch (cnt) {
case 0: if (akku!=0x80) terminate(); break;
case 1: if (akku>elemof(clip.data)-3) terminate(); break;
}
clip.data[cnt++]=akku; nobreak; // Byte ablegen und weiter
default: OCR0A+=T; // = 208 @ 16 MHz für das nächste Bit
}
}
// Zu lange auf Flanke gewartet (F_CPU/64/250 = 1 kHz @ 16 MHz, = 1 ms)
// Vor dem Signal kommt es erwartungsgemäß zu vielen dieser Interrupts
ISR(TIMER0_COMPB_vect) {
terminate();
}
void CLIP::init() {
TCCR0B= 0x02; // F_CPU/8/8; T = 1,024 ms für F_CPU = 16 MHz
ACSRA = 0x18; // Analogvergleicher: Interruptfreigabe, beide Flanken
}
void CLIP::done() {
ACSRA = 0x80; // Interrupts aus
}
| Detected encoding: UTF-8 | 0
|