Source file: /~heha/basteln/Haus/Telefon/CLIP-Anzeige/clip.zip/clip_adc.cpp

// CLIP-Dekoder mit unipolarem A/D-Wandler
#include "ra.h"

union CLIPADC{
 struct{
  int mean;	// Gleitender Mittelwert (Hi/Lo)
 };
 struct{
  byte meanL;
  char meanH;
 };
 static void isr();
 static void terminate();
}clipadc;


void CLIPADC::terminate() {
 if (stat>=16 && cnt) stat=0xFF;
 else stat=0;
 PORTB&=~8;
}
 
// Zählerwert für 1200 Hz
#define T (byte)(F_CPU/16/14/1200+0.5)	// 60

// Verfügbare Zeit: 16 × 14 = 208 Takte
// CPU-Frequenz = 2 MHz (abgesenkt)
// Interruptfrequenz: 1/14 MHz = 71,42 kHz = 14 µs
void CLIPADC::isr() {
 int ac=ADCH-clipadc.meanH;
// Gleitenden Mittelwert bilden (durchgehend)
 clipadc.mean+=ac;
 switch (stat) {
  case 0: {	// Initialisierung
   cnt=akku=det=0;
   clipadc.mean=0;
   ++stat;
  }break;
  case 1: {	// Nur Gleichspannungswert ausmitteln (20 ms)
   add(cnt,1);
   adc0(stat);
  }break;
  case 2: {	// Warten auf etwas Amplitude (200 ms)
   if (ac>10) {	// empirisch!!
    cnt=0;
    stat=13;
   }else{
    add(cnt,1);
    adc0(stat);
    if (stat==13) terminate();	// Kein CLIP gefunden
   }
  }break;
 }
 char n=(ac>>8^GPIOR0)&0x20;	// Polaritätswechsel = Nulldurchgang?
 if (n) {
  if (last>T) {			// Zu hohe Frequenz als Spike ignorieren
   GPIOR0^=0x20;
   dif1=diff;
   diff=last;
   last=0;
   PINB|=4;
  };
 }else{
  if (++last>T) terminate();	// Frequenz zu niedrig, < 500 Hz
 }
 if (!last) switch (stat) {
  case 13: {	// Frequenz messen (256 Nulldurchgänge, < 100 ms)
   add(akku,diff);
   adc0(det);
   add(cnt,1);
   adc0(stat);
  }break;
  case 14: {	// Niedrigere Frequenz suchen (256 Nulldurchgänge, < 20 ms)
   if (diff>det) {
    add(cnt,16);
    adc0(stat);
   }else{
    if (!++cnt) terminate();	// zu lange Präambel
   }
  }break;
  case 15: {	// Startbit suchen (beliebig lange)
   PORTB|=8;
   cnt=0;
   if (diff<det && dif1<det) {
    GPIOR2=T-diff;	// 77 kHz / 64 = 1200 Baud (mit Startzeitpunkt experimentieren!!)
    ++stat;
   }
  }break;
 }
 if (stat>=16 && !--GPIOR2) {
  PORTB&=~8;
  akku>>=1;
  if (diff>det) akku|=0x80;
  switch (++stat) {
   case 26: PORTB|=8; if (!akku&0x80) terminate(); else stat=15; break;
   case 25:
   if (cnt<elemof(clip.data))
   clip.data[cnt++]=akku; nobreak; 	// Byte ablegen und weiter
   default: GPIOR2=T;		// 77 kHz / 64 = 1200 Baud
  }
 }
}

ISR(ADC_vect) {
 clipadc.isr();
}

void CLIP::init() {
PORTB|=2;
 ADMUX = 0xAF;	// ADC6-ADC5, Ergebnis in ADCH
 ADCSRB= 0x90;	// bipolar
 ADCSRA= 0xF9;	// Start mit Taktteiler 2 (F_CPU ist hier 2 MHz)
}

void CLIP::done() {
 ADCSRA= 0;	// Keine weiteren Interrupts
PORTB&=~2;
}
Detected encoding: UTF-80