// 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-8 | 0
|