Quelltext /~heha/basteln/PC/FunkUsb/dcf77franz9.zip/main.cpp

#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-80