#include "dcf77.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/signature.h>
#include <avr/fuse.h>
#include <avr/sleep.h>
#include "dcf77dec.h"
FUSES={
#if F_CPU <= 3000000
0b11111001, // Quarzoszillator 0,9..3 MHz
#elif F_CPU <= 8000000
0b11111101, // Quarzoszillator 3..8 MHz
#else
0b11111111, // Quarzoszillator 8..20 MHz
#endif
0b11010101, // Unterspannungsdetektor 2,7 V, EESAVE
0b11111110, // Selbstprogrammierung
};
// Testprogramm für "dcf77.h"
//
// Ausgabe von UART-Daten und DCF77-Impulse. Sonstige Infos (Quarz, ...) siehe ATtiny85.
//
// - Belegung
// PB2 : Eingang DCF77-Antennensignal (mind. VCC/5000)
// PB1 : Ausgang UART „115200 8N1“ (115200 Baud, acht Datenbits, kein Paritybit, ein Stoppbit)
// PB0 : Ausgang DCF77-Sendeamplitude, nichtinvertiert
/*
Die uprintf-Routine wurde großteils in Assembler umgeschrieben
und unterstützt nun von-neumannisierte Zeiger. Spart erheblich Flash.
Umstellung auf C++ sowie compilergenerierte Logarithmentafel.
Umstellung der Empfangsroutine vom Bottom-Half-Interrupt auf Idle-Prozedur.
Das spart Push-Orgien (damit RAM) und Flash.
Neu ist nun, dass alle Warteschleifen idle() aufrufen müssen.
Umgestellt wurde der Bit-Empfang auf „clevere“ Verteilung auf 8 Bytes.
Das spart long-Schiebeoperationen und damit Flash.
Die Minutenstart-Auswertung kommt nun ohne extra long-Elemente im RAM aus.
Die Schaltsekunde wird beachtet; muss noch getestet werden.
Die Steuerung der LED erfolgt unabhängig von der Hauptschleife,
echte Amplitudenauswertung ohne „Halluzination“:
Die Steuerung in der Hauptschleife gaukelte allzu perfekten Empfang vor.
Kompaktierung der phasensynchronen A/D-Wandler-ISR auf call+rjmp+22+reti ≈ 33 Takte.
(hat 15 MHz / 62000 Hz = 242 Takte Zeit: Prozessor kann mit sleep_cpu() schlafen)
240702 Passt in 4 KByte Flash, aber noch nicht in 256 Byte RAM
Die Amplitudenfindung ist noch viel zu kompliziert und braucht zu viel RAM
für das FIR-Filter. BlockDPC() verbrät 1600 Byte Flash.
Zudem wird eine Vorlage für 08-15-DCF77-Empfangsmodule gebraucht.
240706 Umstellung von FIR- auf IIR-Filter, spart erheblich RAM.
Mittlerweile 66 Byte RAM: Passt locker in ATtiny25,
aber Flash-Bedarf immer noch > 2 KByte.
Dadurch verändern sich die Dezibel-Rechenwerte.
Deshalb habe ich die ganze Umrechnerei weggelassen
und gebe die Binärwerte direkt mit zwei Nachkommastellen aus.
240715 Umstellung BlockDPC() auf Großteil Assembler und 24-Bit-Arithmetik.
Flash-Bedarf ohne serielle Schnittstelle vermutlich < 2 KByte.
Der Test mit USB steht noch aus.
*/
void idle() {
if (GPIOR0&1) { // DPC für Signalprozessor (alle 4 ms)
GPIOR0&=~1;
dcf77.QiBlockDpc();
}else sleep_cpu(); // Strom sparen
}
static void newline() {
UART::Send('\r');
UART::Send('\n');
}
__attribute__((OS_main)) int main() {
MCUCR = 0x20; // Sleep = Idle (ADC und Timer0 bleiben Stromfresser)
ACSR |= 0x80; // Kein Analogvergleicher
GPIOR0= 0; // führt diverse Bits
DDRB = 0b011; // aktiviere Ausgänge
DIDR0 = 0b111; // keine Digitaleingänge
UART::Init();
DCF77::Init();
sei();
uprintf(F("\033[2K\r")); // Zeile löschen, Cursor links
#if 0 // Zum Prüfen der Funktion des Telegrammdekoders
static const PROGMEM DCF77Data testdata99={0x00,0x00,0x28,0x59,0x63,0xC4,0x94,0x99}; // 31.12.2099
static const PROGMEM DCF77Data testdata24={0x00,0x00,0x24,0x59,0x22,0x40,0x3B,0x24}; // 10.07.2024
unsigned Err = dcf77dec.dt=F(testdata24);
dcf77dec.dt.print();
uprintf(F(" Err=%X"),Err);
newline();
Err = dcf77dec.dt=F(testdata99);
dcf77dec.dt.print();
uprintf(F(" Err=%X"),Err);
newline();
++dcf77dec.dt;
dcf77dec.dt.print();
newline();
#endif
for (unsigned iLoop=0; ; iLoop++) {
// warten auf erstes Bit (100 ms nach Sekundenbeginn)
byte twobits = 0;
while (dcf77.get_4ms()!=DCF77::Pickup0) idle();
if (dcf77.get_bit()) twobits|=2; // 1 = keine Trägerabsenkung (59. Minute)
// warten auf zweites Bit (200 ms nach Sekundenbeginn)
while (dcf77.get_4ms()!=DCF77::Pickup1) idle();
if (dcf77.get_bit()) twobits|=1; // 1 = keine Trägerabsenkung = kurzes „dit“ = 0-Bit
char c=twobits&2?twobits&1?'M':'E':twobits&1?'0':'1';
dcf77dec.ProcessVal(twobits);
while (dcf77.get_4ms()!=125) idle(); // bis zur Sekundenmitte warten, damit sich dcf77.lohi setzt
uprintf(F("#%05u\t∆f:% +4i {3~9: Amp=%6,2i ∆=%5,2i} {Amp: L=%6,2i H=%6,2i} Bit: %c"),
iLoop,
dcf77.get_ppm(),
dcf77.getSignal(),
dcf77.getNoise(),
dcf77.getMinAmp(),
dcf77.getMaxAmp(),
c);
uprintf(F(" {%2uL%2u}"), // Zeitpunkte der beiden Flanken. Die erste „zentriert“ sich auf 20.
dcf77.hilo,
dcf77.lowi);
if (dcf77dec.Grade>=2) {
uprintf(F(" | Zeit: "));
dcf77dec.dt.print();
uprintf(F(":%02u %+i"),
dcf77dec.Second,
dcf77dec.Info&4?2:1);
if (twobits&2) uprintf(F(" - sicher %u min"),dcf77dec.Grade);
}
newline();
}
}
Vorgefundene Kodierung: UTF-8 | 0
|