Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- ALLEIN Noch nicht lauffähig.
- Module müsen separiert und in eigens Projekt iengefügt werden.
- Geschrieben für WINAVR bzw GCC für AVR Controller
- ------------------------------------------------------------------------------
- DCF CLOCK My New Version
- für das Pollin DCF Modul, bzw jedes Andere, dass 100, 200 ms Flanken High-Low Produziert
- 12.2019
- Programmed by Christof Ermer
- ------------------------------------------------------------------------------
- */
- /*
- DCF Uhr: Neue Konzepte und Ursource von Ulrich Radig. Inzwischen jedoch völlig verändert-
- Unfertig. Weatherdaten Decoding, weil geheim. Aber mit Separation der Daten
- TWO PARTS
- HEADER UND ANSI_C SOURCE
- 1. HEADER
- 2. C_SOURCE
- 3. MAIN: Abschnitt .H +.C
- Unsiniges selbst rauslöschen
- Darin Enthalten
- I2C LCD, I2C OCF8571 LED LEiste, DAC ,mit LTC
- */
- /*
- 24.11.2019
- Christof Ermer
- Umgeschrieben für ATMega328p Arduino UNO
- Interrupt geändert von INTo auf INT1
- BENUTZE INT1
- ICH BENUTZE DEN INT1 fuer das POLLIN DCF
- Auschalten PON Rausgewrofen
- PON = GND
- VCC= 3.3V !!!!!
- https://xdec.de/msp430-dcf77-empfang-und-auswertung/
- GETESTED NUR mit ATMEGA16
- */
- /*#######################################################################################
- AVR DCF77 Clock
- Copyright (C) 2005 Ulrich Radig
- //Änderungen: Christof Ermer Regensburg
- Pollin DCF...
- Umstellung auf INT1
- gu32DCF_msTimerSync
- gu32MS_NOW
- #######################################################################################*/
- #ifndef _POLLIN_CLOCK_H
- #define _POLLIN_CLOCK_H
- #define SETBOP |=
- #define CLRBOP &= ~
- #define DCF_BEEP_DDRX DDRD
- #define DCF_BEEP_PORT PORTD
- #define DCF_BEEP_BIT (1<<PD4)
- #define BEEP_INIT() (DCF_BEEP_DDRX |= DCF_BEEP_BIT)
- #define BEEP_ON() (DCF_BEEP_PORT |= DCF_BEEP_BIT)
- #define BEEP_OFF() (DCF_BEEP_PORT &= ~DCF_BEEP_BIT)
- #define BEEP_KNACKS_MS 5
- #define BEEP_SHORT_MS 25
- #define BEEP_LONG_MS 100
- #define BEEP_PAUSE 3
- #define DCF_NULL_TIME 950
- #define DEBOUNCE_TO_SHORT_MS 90
- //250 Ticks/Sekunde = 0,25 Tick/milisekunde
- #define DCF_Sec_Puls 0x01
- #define DCF_INT_SEC 0x02
- #define DCF_RISING_INT 0x04
- #define DCF_FALLING_INT 0x08
- #define DCF_SYNC 0x10
- // --
- #define DCF_DETECT_L 0x40
- #define DCF_DETECT_H 0x80
- //volatile uint8_t gu8DCF_Status;
- #define DCF_NOSIGNAL_TIMEOUT 2300
- //Ausschalten wenn nicht benötigt
- #define POLLIN_DCF // USER BESTIMMTE HARDWARE SELBST ANPASSEN
- #ifdef POLLIN_DCF
- /*
- #define PON (1<<PD4)
- #define DCF_PORT PORTD
- #define DCF_DIRECTION_PORT DDRD
- #define DCF_DDR_INIt() (DCF_DIRECTION_PORT |= PON)
- #define DCF_STOP() (DCF_PORT |= PON) //DCF AUSSCHALTEN
- #define DCF_RUN() (DCF_PORT &= ~PON) //DCF EINSCHALTEN
- // ~1Sec.
- Erledigt 10µF an 10K Integrator
- */
- #define DCF_INTX_PORTX PORTD
- #define DCF_INTX_DDRX DDRD
- #define DCF_INTX_DATA_BIT (1<<PD3) //INT1
- #define DCF_INTX_DDRX_INIT() (DCF_INTX_DDRX &= ~DCF_INTX_DATA_BIT)
- #endif
- // =================================================================
- //Interface
- //#define USE_INT0
- #define USE_INT1
- #if defined (__AVR_ATmega328P__)
- #define INTX_EDGE_CTRL_REG EICRA
- #ifdef USE_INT0
- #define DCF77_INT_VECT INT0_vect
- #define DCF77_INT_ENABLE() (EIMSK |= (1<< INT0));
- #define DCF77_INT_DISABLE() (EIMSK &= ~(1<< INT0));
- #define CLEAR_INTX_FLAG() (EIFR = (1<<INTF0)) // MIT "="
- #define INT_X_EDGE_MASK ((1<< ISC01) | (1<< ISC00))
- #define INT_X_FALLING_EDGE_BITS (1<< ISC01)
- #define INT_X_RISING_EDGE_BITS ((1<< ISC01) | (1<< ISC00))
- //#endif
- //#ifdef USE_INT1
- #else
- #define DCF77_INT_VECT INT1_vect
- #define DCF77_INT_ENABLE() (EIMSK |= (1<< INT1));
- #define DCF77_INT_DISABLE() (EIMSK &= ~(1<< INT1));
- #define CLEAR_INTX_FLAG() (EIFR = (1<<INTF1)) // MIT "="
- #define INT_X_EDGE_MASK ((1<< ISC11) | (1<< ISC10))
- #define INT_X_FALLING_EDGE_BITS (1<< ISC11)
- #define INT_X_RISING_EDGE_BITS ((1<< ISC11) | (1<< ISC10))
- #endif
- #define INT_X_FALLING_EDGE() (EICRA = ((EICRA & ~INT_X_EDGE_MASK) | INT_X_FALLING_EDGE_BITS))
- #define INT_X_RISING_EDGE() (EICRA = ((EICRA & ~INT_X_EDGE_MASK) | INT_X_RISING_EDGE_BITS))
- //TIMSK1 = bit (TOIE1);
- #endif //(__AVR_ATmega328P__)
- #if defined (__AVR_ATmega16__)
- //Interrupt an dem das DCF77 Modul hängt hier INT1
- #define DCF77_INT_ENABLE() GICR |= (1<<INT1);
- #define DCF77_INT_DISABLE() GICR &= ~(1<<INT1);
- #define DCF77_INT INT1_vect //SIG_INTERRUPT1
- #define INT1_CONTROL MCUCR
- //RICHTIG
- //#define INT0_FALLING_EDGE 0x02
- //#define INT0_RISING_EDGE 0x03
- //RICHTIG
- #define INT1_FALLING_EDGE 0x08
- #define INT1_RISING_EDGE 0x0C
- #define TIMSK1 TIMSK
- #endif
- #if defined (__AVR_ATmega32__)
- //Interrupt an dem das DCF77 Modul hängt hier INT1
- #define DCF77_INT_ENABLE() GICR |= (1<<INT1);
- #define DCF77_INT_DISABLE() GICR &= ~(1<<INT1);
- #define DCF77_INT INT1_vect
- #define INT1_CONTROL MCUCR
- #define INT1_FALLING_EDGE 0x08 // 0x02
- #define INT1_RISING_EDGE 0x0C //0x03
- #define TIMSK1 TIMSK
- #endif
- #if defined (__AVR_ATmega8__)
- //Interrupt an dem das DCF77 Modul hängt hier INT1
- #define DCF77_INT_ENABLE() GICR |= (1<<INT1);
- #define DCF77_INT_DISABLE() GICR &= ~(1<<INT1);
- #define DCF77_INT INT1_vect
- #define INT1_CONTROL MCUCR
- #define INT1_FALLING_EDGE 0x08
- #define INT1_RISING_EDGE 0x0C
- #define TIMSK1 TIMSK
- #endif
- #if defined (__AVR_ATmega88__)
- //Interrupt an dem das DCF77 Modul hängt hier INT1
- #define DCF77_INT_ENABLE() EIMSK |= (1<<INT1);
- #define DCF77_INT_DISABLE() EIMSK &= ~(1<<INT1);
- #define DCF77_INT INT1_vect
- #define INT1_CONTROL EICRA
- #define INT1_FALLING_EDGE 0x08
- #define INT1_RISING_EDGE 0x0C
- #endif
- //http://www.c-howto.de/tutorial/strukturierte-datentypen/bitfelder/
- //Structur des gu64DCF_rx_buffer
- typedef struct
- {
- unsigned char M :1 ;
- unsigned int Weather :14 ;
- /*
- unsigned char O1 :1 ; //Weather
- unsigned char O2 :1 ; //Kodierung nach Bedarf
- unsigned char O3 :1 ;
- unsigned char O4 :1 ;
- unsigned char O5 :1 ;
- unsigned char O6 :1 ;
- unsigned char O7 :1 ;
- unsigned char O8 :1 ;
- unsigned char O9 :1 ;
- unsigned char O10 :1 ;
- unsigned char O11 :1 ;
- unsigned char O12 :1 ;
- unsigned char O13 :1 ;
- unsigned char O14 :1 ;
- */ unsigned char R :1 ;
- unsigned char A1 :1 ;
- unsigned char Z1 :1 ;
- unsigned char Z2 :1 ;
- unsigned char A2 :1 ;
- unsigned char S :1 ;
- unsigned char Min :7 ;//7 Bits für die Minuten
- unsigned char P1 :1 ;//Parity Minuten
- unsigned char Hour :6 ;//6 Bits für die Stunden
- unsigned char P2 :1 ;//Parity Stunden
- unsigned char Day :6 ;//6 Bits für den Tag
- unsigned char Weekday :3 ;//3 Bits für den Wochentag
- unsigned char Month :5 ;//3 Bits für den Monat
- unsigned char Year :8 ;//8 Bits für das Jahr **eine 5 für das Jahr 2005**
- unsigned char P3 :1 ;//Parity von P2
- }DCF77_BITS_TYPE;
- typedef union
- {
- DCF77_BITS_TYPE bitRx_Buffer;
- uint64_t u64DCF_RxBuffer; //ull
- }DCF77_UNION_T;
- typedef struct
- {
- volatile char parity_err :1;//0 Hilfs Parity
- volatile char parity_P1 :1;//1 Berechnetes Parity P1
- volatile char parity_P2 :1;//2 Berechnetes Parity P2
- volatile char parity_P3 :1;//3 Berechnetes Parity P3
- volatile char dcf_rx :1;//4 Es wurde ein Impuls empfangen
- volatile char dcf_sync :1;//5 In der letzten Minuten wurde die Uhr syncronisiert
- volatile char dcf_NoSignal :1;//6
- volatile char dcf_SecPuls :1;//7
- volatile uint8_t dcf_WeatherSquCnt :2; // 0=Nothing 1..2..3
- volatile char dcf_Plip :1;//8 1== sec
- volatile char dcf_Beep :1;//9 1== sec in Int erledigt
- volatile char dcf_BeepLong :1;//10 1== sec in Int erledigt
- }ST_DCF_FLAGS_TYPE;
- //gstDCF_Flags;
- typedef struct
- {
- unsigned char Tag :4; //0..3
- unsigned char Nacht :4; //4..7
- unsigned char HeavyWheather :4; //8..11
- //Bit 15=0 aktueller Tag B15=1
- unsigned char Regenwahrsch :3; //12..14
- unsigned char SwitchBit_8_11 :1; //15
- unsigned char Temperatur :6; //16.21
- unsigned char Prognose_Tag :4;
- unsigned char Prognose_Nacht :4;
- }DCF_WEATHERTYPE;
- //64 Bit für DCF77 benötigt werden 59 Bits
- //RX Pointer (Counter)
- extern volatile ST_DCF_FLAGS_TYPE gstDCF_Flags;
- extern volatile DCF77_UNION_T gstunDCF77_Bits; // union Struct
- extern volatile uint8_t gu8DCF_Status;
- extern volatile unsigned char gu8Rx_BitCnt;
- extern volatile uint16_t gu16aWeatherSeq[3];
- extern volatile uint64_t gu64Weather;
- extern volatile uint8_t gu8aWeatherData[5];
- extern volatile uint16_t gu16Pulsweite;
- extern volatile uint32_t gu32DCF_msTimerSync;
- extern volatile unsigned char ss; //Globale Variable für Sekunden
- extern volatile unsigned char mm; //Globale Variable für Minuten
- extern volatile unsigned char hh; //Globale Variable für Stunden
- extern volatile unsigned char day; //Globale Variable für den Tag
- extern volatile unsigned char mon; //Globale Variable für den Monat
- extern volatile unsigned int year; //Globale Variable für den Jahr
- extern void Start_Clock(void); //Startet die DCF77 Uhr
- extern void Plip(uint8_t u8ZZ);
- #endif //_CLOCK_H
- =============================================================
- C_SOUCRE
- =============================================================
- /*#######################################################################################
- 20.11.2019 Christof Ermer - Regensburg
- https://gist.github.com/kronoc/c669eb8cceece1ea7f7ce3f964c511ee
- AVR AT328 DCF77 Clock
- DCF 77 Clock org. by Ulrich Radig,
- Sehr stark Modifiziert bei Christof Ermer - Regensburg
- Gänzlich andere Timerverwendung, UNION Typedef für die Daten etc..
- IDEE:
- https://www.ulrichradig.de/home/index.php/avr/dcf77_uhr
- https://www.ulrichradig.de/home/index.php/news/59/86/Bei-Radig-Hard-Software-01.08.2019
- Copyright (C) 2005 Ulrich Radig
- http://www.gjlay.de/software/dcf77/konzept.html
- http://www.netzmafia.de/skripten/hardware/RasPi/Projekt-DCF77/
- https://www.mikrocontroller.net/articles/DCF77_Wetterinformationen
- https://dcf77logs.de/wetter
- http://www.fact4ward.com/blog/meteotime/
- http://arduino-projects4u.com/pdf/DB%20W-Protokoll-V%201.pdf
- https://www.mikrocontroller.net/topic/61886#650725
- https://xdec.de/msp430-dcf77-empfang-und-auswertung/
- https://www.mikrocontroller.net/topic/97295
- https://www.arduinoclub.de/2013/11/15/dcf77-dcf1-arduino-pollin/
- Hier für sketch
- https://www.issb.de/mw/index.php/Test_elektronischer_Funkuhren-Module_(DCF77)_am_Mikroconcroller
- https://www.arduinoclub.de/2013/11/15/dcf77-dcf1-arduino-pollin/
- https://www.fingers-welt.de/phpBB/viewtopic.php?f=14&t=8161
- https://pic-projekte.de/blog/dcf77/
- PON MUSS !!!! 1 SEKUND EHIGH, DANN LOW WERDEN. ALSO DOCH!
- ACHTUNG
- Pollin Pinbelegung ist falsch in einem der gefundnen Dokus. Data udn PON vertausch. Pon liegt aussen.
- PON (v+3.3V) 10µF an 10K gegen MasseIntegrator
- Richtig =
- AUSSENliegend =PON =
- TCO
- GND = GND
- Etwas nach Innen VCC = 3.3V MAX
- AVR DCF77 Clock
- https://www.ulrichradig.de/home/index.php/avr/dcf77_uhr
- https://www.ulrichradig.de/home/index.php/news/59/86/Bei-Radig-Hard-Software-01.08.2019
- Copyright (C) 2005 Ulrich Radig
- https://www.mikrocontroller.net/topic/97295
- https://www.arduinoclub.de/2013/11/15/dcf77-dcf1-arduino-pollin/
- http://www.netzmafia.de/skripten/hardware/RasPi/Projekt-DCF77/
- Hier für sketch
- https://www.issb.de/mw/index.php/Test_elektronischer_Funkuhren-Module_(DCF77)_am_Mikroconcroller
- https://www.arduinoclub.de/2013/11/15/dcf77-dcf1-arduino-pollin/
- https://www.fingers-welt.de/phpBB/viewtopic.php?f=14&t=8161
- https://pic-projekte.de/blog/dcf77/
- https://xdec.de/msp430-dcf77-empfang-und-auswertung/
- PON MUSS !!!! 1 SEKUNDE HIGH, DANN LOW WERDEN. ALSO DOCH!
- ACHTUNG
- pollin Pinbelegung ist falscch
- Richtig =
- AUSSENliegend =PON = GND Feyst auf GROUND
- TCO
- GND = GND
- Etwas nach Innen VCC = 3.3V MAX
- USES TIMER1 fuer 1 Sekundne Interrrupt
- Das ist zu teuer
- T= mit OCR1A = 250 ist ebenfalls sehr genau
- T/256-. OCR 250 = 250
- USED INTererupt = INT_1
- T1= 15625 Hz
- aber durch PReload von 65535-- (F_CPU / 1024)
- TCNT1 = 65535U - (F_CPU / 1024)
- //65535U - 15625 =
- Zähle von 49910 auf 65536 = 15625 bei 15625Hz = 1 Sekunde !!
- ALSO letzlich genau eine Sekunde!!
- Google
- DCF77 PSeudozufallszahl
- Es steck in jedem Bit noch eine FM 256 Bit Info
- Damit ist die Zeit NOCH sehr viel genauer
- MIt EXOR eine PLL Vergleich REFERENZ- Empfangsphase um Phase der Referenz nachzuziehen, sonst Schwebung.
- Pahsenvoreiluing testen welche vor, oder nachgeht, via Interrrupt auf XOR
- https://www.meinberg.de/german/info/dcf77.htm
- if X<9 ? :
- */
- /*
- #include <avr/io.h>
- #include <avr/interrupt.h>
- */
- #include "main.h"
- //#include "FunkclockNew.h"
- volatile uint32_t gu32DCF_msFreeRuner=0;
- volatile uint32_t gu32DCF_msTimerSync=0;
- volatile uint16_t gu16Pulsweite=0;
- volatile unsigned char gu8Rx_BitCnt = 0;
- volatile ST_DCF_FLAGS_TYPE gstDCF_Flags;
- volatile DCF77_UNION_T gstunDCF77_Bits; // union Struct
- volatile uint16_t gu16aWeatherSeq[3];
- volatile uint64_t gu64Weather=0;
- volatile uint8_t gu8aWeatherData[5];
- volatile uint8_t gu8DCF_Status = 0;
- volatile uint32_t gu32MS_NOW =0;
- //Bitzähler für RX Bit
- //64 Bit für DCF77 benötigt werden 59 Bits
- /*
- gstunDCF77_Bits.bitRx_Buffer
- gstunDCF77_Bits.u64DCF_RxBuffer
- */
- //Die Uhrzeit seht in folgenden Variablen
- volatile unsigned char ss = 0; //Globale Variable für die Sekunden
- volatile unsigned char mm = 0; //Globale Variable für die Minuten
- volatile unsigned char hh = 0; //Globale Variable für die Stunden
- volatile unsigned char day = 0; //Globale Variable für den Tag
- volatile unsigned char mon = 0; //Globale Variable für den Monat
- volatile unsigned int year = 0; //Globale Variable für das Jahr
- /* **** WETTER *****
- https://www.mikrocontroller.net/articles/DCF77_Wetterinformationen
- 3* 14 BITS = 42 Bit
- DCF Protokoll ist hinreichend bekannt.
- Es gibt 14 Datenbits, in 3 Minuten wird ein Datensatz übertragen (= 42 bit)
- 90 Regionen, 4 mal täglich Informationen, jeweils 3 Minuten: ergibt 1080 Sendeminuten pro Tag (1440 Minuten). Rest 360 (5040 bit).
- 4 mal täglich werden Infos zu einer Zone gesendet:
- * 22:00 - 03:59 Aktueller / kommender Tag (TODAY im Display)
- * 04:00 - 09:59 Folgender Tag (DAY 1 im Display)
- * 10:00 - 15:59 Darauffolgender Tag (DAY 2 im Display)
- * 16:00 - 18:59 Darauffolgender Tag (DAY 3 im Display)
- * 19:00 - 21:59 30 Zusatzregionen mit 2-Tages-Prognose
- http://www.wetterstationen.info/mete-on-1.php
- Die Daten sind verschlüsselt
- Die entschlüsselten Daten können dekodiert werden
- http://www.hkw-elektronik.de/pdf/DB%20W-Protokoll-V%201.pdf
- */
- //Hilfs Sekunden Counter
- volatile unsigned int gu16H_ss = 0;
- //Hilfs Variable für Stundenwechsel
- volatile unsigned int gu16H_hh = 0;
- // PRPTO
- void Add_one_Second (void);
- void Plip(uint8_t u8ZZ);
- /*
- //############################################################################
- void Try_Interrupt_Debounce(void) //for bad signalquality
- {
- static uint32_t u3DCF_IntTime; //Merk Dir die Zeit
- if( gstDCF_Flag & DCF_EVENT )
- {
- DCF77_INT_DISABLE(); //lösche alle ints, weil störungen
- INT_FLAG_REG |= (1 << INTF1); // lösche flag, Siehe pdf
- gstDCF_Flag &= INTSTATUS_CLR_INT_MASK;
- gstDCF_Flag |= DCF_DISABLED;
- u3DCF_IntTime = gu32_Ticks;
- };
- if( gstDCF_Flag & DCF_DISABLED )
- {
- if( gu32_Ticks >= (u3DCF_IntTime + DELAY_INT_WIEDER_ON) )
- {
- //244 Ticks/Sekunde ind 24 pro 100MS
- //Weil da sSignal so schlecht ist.... einfach unerwünschtes aussprren
- INT_FLAG_REG = (1<< INTF1); // lösche alle INT Ereignisse // Siehe pdf
- gstDCF_Flag &= INTSTATUS_CLR_INT_MASK;
- DCF77_INT_ENABLE(); // INT Wieder einschalten nach eine rguten Zeit
- };
- };
- };
- */
- //PROTO
- // ********************************
- void DCF_Zyklus_59_Fertig( void );
- // ********************************
- // ********************
- void ResetDCFBuf(void)
- // ********************
- {
- gu8Rx_BitCnt = 0;
- gstunDCF77_Bits.u64DCF_RxBuffer = 0;
- gstDCF_Flags.parity_err = 0;
- gstDCF_Flags.parity_P1 = 0;
- gstDCF_Flags.parity_P2 = 0;
- gstDCF_Flags.parity_P3 = 0;
- };
- //############################################################################
- //Diese Routine startet und inizialisiert den Timer
- void Start_Clock(void)
- //############################################################################
- {
- DCF_INTX_DDRX_INIT();
- INT_X_RISING_EDGE();
- CLEAR_INTX_FLAG();
- DCF77_INT_ENABLE();
- //PON richtig bedienen, beim Pollin DCF:
- //Integrator (V+)10µF-C und 10K gegen Masse. = H.L
- ResetDCFBuf();
- ss = 0; //Globale Variable für die Sekunden
- mm = 0; //Globale Variable für die Minuten
- hh = 0; //Globale Variable für die Stunden
- day = 0; //Globale Variable für den Tag
- mon = 0; //Globale Variable für den Monat
- year = 0; //Globale Variable für das Jahr
- gstDCF_Flags.parity_err = 0;
- gstDCF_Flags.parity_P1 = 0;
- gstDCF_Flags.parity_P2 = 0;
- gstDCF_Flags.parity_P3 = 0;
- gstDCF_Flags.dcf_sync = 0;
- //Interrupt DCF77 einschalten auf ansteigende Flanke
- // NUTZE TIMER 2 für 1000 Hz Interrupt = ms Auflösung
- TCNT2 = 0;
- TCCR2A=(11<< WGM21); //CTC
- TIMSK2 = (1 << OCIE2A); //OIE2
- TIFR2 = (1 << OCF2A); // Flag weg mit "="
- OCR2A =250;
- //Setzen des Prescaler auf 64
- TCCR2B = (1<< CS22); // = 1000/sec
- gu32DCF_msFreeRuner = 0;
- gu32DCF_msTimerSync = 0;
- };
- // ############################################################################
- //Overflow Interrupt wird ausgelöst bei 59Sekunde oder fehlenden DCF77 Signal
- ISR(TIMER2_COMPA_vect) //TIMER2_OVF_vect
- //############################################################################
- {
- cli(); // Damit kein anderer Int dazuischenpfuzscht
- gu32DCF_msFreeRuner++; //no reset
- gu32DCF_msTimerSync++; //perioidisch 0 gestellt bis 59 fertig, dann 1000
- sei();
- if( gu32DCF_msTimerSync >= 1000 ) //Sekunde
- {
- gu32DCF_msTimerSync = 0;
- DCF_Zyklus_59_Fertig();
- };
- if( (gu32DCF_msFreeRuner - gu32MS_NOW) > DCF_NOSIGNAL_TIMEOUT )
- {
- gstDCF_Flags.dcf_NoSignal = 1;
- }
- else
- {
- gstDCF_Flags.dcf_NoSignal = 0;
- };
- };
- // *****************************
- void DCF_Zyklus_59_Fertig(void)
- // *****************************
- {
- //struct DCF77_Bits * gstunDCF77_Bits.bitRx_Buffer = (struct DCF77_Bits*)(char*)&gstunDCF77_Bits.u64DCF_RxBuffer;
- //wurden alle 59 Bits empfangen und sind die Paritys richtig?
- if(gu8Rx_BitCnt > 59) {Start_Clock();};
- if( (gu8Rx_BitCnt == 59) && //==
- (gstDCF_Flags.parity_P1 == gstunDCF77_Bits.bitRx_Buffer.P1) &&
- (gstDCF_Flags.parity_P2 == gstunDCF77_Bits.bitRx_Buffer.P2) &&
- (gstDCF_Flags.parity_P3 == gstunDCF77_Bits.bitRx_Buffer.P3)
- )
- //Alle 59Bits empfangen stellen der Uhr nach DCF77 Buffer
- {
- //Berechnung der Minuten BCD to HEX
- mm = gstunDCF77_Bits.bitRx_Buffer.Min-((gstunDCF77_Bits.bitRx_Buffer.Min/16)*6);
- if(mm != 0)
- {mm--;}
- else
- {mm = 59; gu16H_hh = 1;};
- //Berechnung der Stunden BCD to HEX
- hh = gstunDCF77_Bits.bitRx_Buffer.Hour-((gstunDCF77_Bits.bitRx_Buffer.Hour/16)*6);
- if (gu16H_hh) {hh--; gu16H_hh = 0;};
- //Berechnung des Tages BCD to HEX
- day= gstunDCF77_Bits.bitRx_Buffer.Day-((gstunDCF77_Bits.bitRx_Buffer.Day/16)*6);
- //Berechnung des Monats BCD to HEX
- mon= gstunDCF77_Bits.bitRx_Buffer.Month-((gstunDCF77_Bits.bitRx_Buffer.Month/16)*6);
- //Berechnung des Jahres BCD to HEX
- year= 2000 + gstunDCF77_Bits.bitRx_Buffer.Year-((gstunDCF77_Bits.bitRx_Buffer.Year/16)*6);
- //Sekunden werden auf 0 zurückgesetzt
- ss = 59;
- gstDCF_Flags.dcf_sync = 1;
- gu8DCF_Status |= DCF_SYNC;
- gstDCF_Flags.dcf_BeepLong = 1;
- /*
- WEATHER
- MIN =? Modulo 3
- DMY:27-11-2019 Time: 09:34:58 Sync:1 Rx:0
- DCFstat:10111010 RxCnt:59
- DCF_FLAGS_10111011
- DCF:0000010001100110001011100111000100100110101101000100100001110000
- Weather_1: 0010110000010110 Weather_2: 0011110111010101 Weather_3: 0001101010010001
- Weather_64:0000000000000000000000000000000001000111110111010101101100001011
- 110101001000111110111010101101100001011
- Weather_5Byte: W5: 00000000 W4: 01000111 W3: 11011101 W2: 01011011 W1: 00001011
- */
- gu16aWeatherSeq[ mm % 3 ] = gstunDCF77_Bits.bitRx_Buffer.Weather;
- //14 Bit / wort
- gu64Weather = ((gu16aWeatherSeq[0] & 0x7E) >> 1); // 1.2 6 bit, Blende 0 & 7 aus
- gu64Weather |= ((gu16aWeatherSeq[0] & 0x3F00UL) >> 2); //= 12 BIT 2. 8 bit Rücke nach
- gu64Weather |= ((gu16aWeatherSeq[1] & 0x3FFFUL) << 12); //
- gu64Weather |= ((gu16aWeatherSeq[2] & 0x3FFFULL) << 26 );
- gu8aWeatherData[0]= (gu64Weather & 0xFF);
- gu8aWeatherData[1]= ( (gu64Weather >> 8) & 0xFF);
- gu8aWeatherData[2]= ( (gu64Weather >> 16) & 0xFF);
- gu8aWeatherData[3]= ( (gu64Weather >> 24) & 0xFF);
- gu8aWeatherData[4]= ( (gu64Weather >> 32) & 0xFF);
- // STIMMMTZ NICHT 14 BIT Runterbrechen auf 5*14=50 Bit
- }
- else
- {
- Add_one_Second();
- gstDCF_Flags.dcf_sync = 0;
- };
- //CLEAR ALL
- //zurücksetzen des RX Bit Counters
- ResetDCFBuf();
- };
- //############################################################################
- //DCF77 Modul empfängt Träger
- ISR (DCF77_INT_VECT) //INT_X Intererrupt
- //############################################################################
- {
- unsigned int uiPulseWide;
- //DCF77_INT_DISABLE();
- //Auswertung der Pulseweite
- if( (INTX_EDGE_CTRL_REG & INT_X_EDGE_MASK) == INT_X_RISING_EDGE_BITS)
- {
- gu8DCF_Status &= ~DCF_FALLING_INT;
- gu8DCF_Status |= DCF_RISING_INT;
- gstDCF_Flags.dcf_NoSignal = 0;
- gstDCF_Flags.dcf_rx ^= 1;
- //Sekunden Hilfs Counter berechnen
- gu16H_ss += (gu32DCF_msTimerSync % 1000);
- cli();
- gu32DCF_msTimerSync = 0; // Zurücksetzen Aufruftimer
- gu32MS_NOW = gu32DCF_msFreeRuner; // STARTzeit MERKEN steigende Flanke
- sei(); // //Zurücksetzen des Timers
- ///ist eine Secunde verstrichen //
- if (gu16H_ss > 900) //900=ms 90% von 1Sekunde
- {
- //Addiere +1 zu Sekunden
- Add_one_Second();
- gu16H_ss = 0;
- gu8DCF_Status |= DCF_INT_SEC;
- //Zurücksetzen des Hilfs Counters
- }
- //Nächster Interrupt wird ausgelöst bei abfallender Flanke
- CLEAR_INTX_FLAG();
- INT_X_FALLING_EDGE();
- }
- else //Fallend EDGE
- {
- gu8DCF_Status &= ~DCF_RISING_INT;
- gu8DCF_Status |= DCF_FALLING_INT;
- //Auslesen der Pulsweite von ansteigender Flanke zu abfallender Flanke
- cli();
- uiPulseWide = gu32DCF_msFreeRuner - gu32MS_NOW; // Pulslänge
- gu32DCF_msTimerSync = 0; // Zurücksetzen Aufruftimer
- sei();
- // *********************
- gu16Pulsweite = uiPulseWide; //NUR UM ES ANZEIGEN ZU KÖNNEN
- // *********************
- if( uiPulseWide > DEBOUNCE_TO_SHORT_MS ) // <90ms
- {
- //Sekunden Hilfs Counter berechnen
- gu16H_ss += uiPulseWide;
- //Parity speichern
- //beginn von Bereich P1/P2/P3
- if(gu8Rx_BitCnt == 21 || gu8Rx_BitCnt == 29 || gu8Rx_BitCnt == 36)
- {
- gstDCF_Flags.parity_err = 0;
- };
- //Speichern von P1
- if (gu8Rx_BitCnt == 28) {gstDCF_Flags.parity_P1 = gstDCF_Flags.parity_err;};
- //Speichern von P2
- if (gu8Rx_BitCnt == 35) {gstDCF_Flags.parity_P2 = gstDCF_Flags.parity_err;};
- //Speichern von P3
- if (gu8Rx_BitCnt == 58) {gstDCF_Flags.parity_P3 = gstDCF_Flags.parity_err;};
- //Überprüfen ob eine 0 oder eine 1 empfangen wurde
- //0 = 100ms
- //1 = 200ms
- //Abfrage größer als 150ms (15% von 1Sekund also 150ms)
- if( uiPulseWide > 150 )
- {
- //Schreiben einer 1 im gu64DCF_gstunDCF77_Bits.bitRx_Buffer an der Bitstelle gu8Rx_BitCnt
- gstunDCF77_Bits.u64DCF_RxBuffer |= (1ULL << gu8Rx_BitCnt);
- //Toggel Hilfs Parity
- // ?????????????????????????????????????????????????????????????????????????
- gstDCF_Flags.parity_err ^= 1;
- gu8DCF_Status|= DCF_DETECT_H;
- gu8DCF_Status &= ~DCF_DETECT_L;
- }
- else // 0
- {
- //gu8ProgStatusFlags |= BEEP100MS;
- //gstunDCF77_Bits.u64DCF_RxBuffer &= ~(1ULL << gu8Rx_BitCnt);
- gu8DCF_Status |= DCF_DETECT_L;
- gu8DCF_Status &= ~DCF_DETECT_H;
- };
- //RX Bit Counter wird um 1 incrementiert
- gu8Rx_BitCnt++;
- //Nächster Interrupt wird ausgelöst bei ansteigender Flanke
- //Nächster Interrupt wird ausgelöst bei ansteigender Flanke
- CLEAR_INTX_FLAG() ;
- INT_X_RISING_EDGE();
- }; // to short Debounce
- };
- };
- //############################################################################
- //Addiert 1 Sekunde
- void Add_one_Second(void)
- //############################################################################
- {
- ss++;//Addiere +1 zu Sekunden
- if (ss == 60)
- {
- ss = 0;
- mm++;//Addiere +1 zu Minuten
- if (mm == 60)
- {
- mm = 0;
- hh++;//Addiere +1 zu Stunden
- if (hh == 24)
- {
- hh = 0;
- };
- }
- }
- gstDCF_Flags.dcf_SecPuls = 1;
- };
- // *************************************
- void Plip(uint8_t u8ZZ)
- // *************************************
- {
- BEEP_INIT(); //WEGEN SUMMER
- if(gu8ProgStatusFlags & BEEP_TON_ON)
- {
- DCF_BEEP_PORT |= DCF_BEEP_BIT;
- wdt_reset(); //WATCHDOG!
- _delay_ms( u8ZZ );
- wdt_reset(); //WATCHDOG!
- DCF_BEEP_PORT &= ~DCF_BEEP_BIT;
- };
- };
- ============================================================
- MAIN HEADER
- =================================
- // Versoon 20.11.2019
- #ifndef MAIN_HEADER //Prevents multiple includes
- #define MAIN_HEADER
- #include <stdio.h>
- #include <avr/sfr_defs.h>
- #include <stdlib.h>
- #include <avr\io.h>
- #include <util\delay.h>
- #include <ctype.h>
- #include <avr/wdt.h>
- #include <avr\interrupt.h>
- #include <string.h>
- #include <avr/pgmspace.h>
- #include <math.h>
- #include "PCF8574.h"
- #include "max7219.h"
- #include "uart328.h"
- #include "i2cmaster.h"
- #include "i2clcd.h"
- #include "debug.h"
- #include "ServiceFunc.h"
- #include "Befehle.h"
- #include "max7219.h"
- #include "LT1057_DAC.h"
- //#include "Funkclock.h"
- #include "FunkclockNew.h"
- //#define LED1_BLINK (1<<PB5) //LED an BIT 0
- #define PCF8574_LED_AR 0x27 //Alle Jumper Linkszum chip = V+
- // in Befehle.h: #define UART_BAUD_RATE 115200UL //UART_BAUD_SELECT_DOUBLE_SPEED
- // Hardwareassignment
- //PORTD TX/RX ERST MAL FÜR FLAGS
- #define PD0_RX_BIT 0x01 //PIN2
- #define PD1_TX_BIT 0x02 //PIN3
- //RUNDUNG
- //16MHZ /72000 -> 222.2222222... = oCR0A=222
- // 16000000 / 244 = ~72072
- //#define TICK_1000MS 72072UL
- #define TICK_1000MS 250U
- //#define TICK_100MS 7207U
- #define TICK_DAC_N250 10
- #define STATUS_TICK_EVENT 0x01
- #define STATUS_DAC_EVENT 0x02
- #define HELP_SEC_GR_900 0x04
- #define PLIP_SHORT 0x10
- #define BEEP100MS 0x20
- #define BEEP200MS 0x40
- #define BEEP_TON_ON 0x80
- //gu8ProgStatusFlags
- //INTERNE LED
- #define INTLED_NR 5
- #define INTLED_PORT PORTB
- #define INTLED_DDR DDRB
- #define INTLED_INIT() (INTLED_DDR |= (1<<INTLED_NR))
- #define TOGGLE_INTLED() (INTLED_PORT ^= (1<<INTLED_NR))
- #define SET_INTLED() (INTLED_PORT |= (1<<INTLED_NR))
- #define CLR_INTLED() (INTLED_PORT &= ~(1<<INTLED_NR))
- extern volatile uint32_t gu32_Ticks;// T2 timeCounter
- extern volatile uint8_t gu32DAC_Tick;
- extern volatile uint8_t gu8ProgModeFlag;
- extern volatile uint8_t gu8ProgStatusFlags;
- extern volatile float gfSollFRQ; //Hz
- #endif //MAIN_HEADER
- =============================================
- Main C
- =======================================
- //------------------------------------------------------------------------------
- // Programmed by Christof Ermer
- //------------------------------------------------------------------------------
- #define DATUM "Version 19.11.2019"
- #define SOFTWARE "DCF Pollin Receiver-V1.3"
- #define HARDWARE "Arduino-UNO ATMega328"
- #define AUTOR "Christof Ermer"
- #define IHAVENOBRAIN "I have no brain."
- #define USEYOURS " Use your own!"
- #include "main.h"
- // GLOBALE VARIABLEN
- volatile uint32_t gu32_Ticks; // T2 TimerCounter
- volatile uint8_t gu8ProgStatusFlags;
- volatile uint8_t gu32DAC_Tick = TICK_DAC_N250;
- volatile float gfSollFRQ = 77500.0; //Hz
- // ***************************
- ISR( TIMER0_COMPA_vect ) //250 Hz
- /// ***************************
- {
- gu32_Ticks++;
- UART_RX_Check();
- if( !(gu32_Ticks % TICK_1000MS) )
- {
- gu8ProgStatusFlags |= STATUS_TICK_EVENT;
- };
- if( !(gu32_Ticks % gu32DAC_Tick) )
- {
- gu8ProgStatusFlags |= STATUS_DAC_EVENT;
- };
- gu8ProgStatusFlags |= STATUS_DAC_EVENT;
- };
- // *************
- int main(void)
- // *************
- {
- uint8_t u8NN=0;
- uint16_t u16DAC;
- uint16_t u16DAC_Cnt =0;
- uint32_t u32CPULoops=0;
- INTLED_INIT();
- wdt_reset();
- wdt_enable(WDTO_1S); //500mS Totmannknopf
- Init_UART( UART_BAUD_RATE ); //Befehle.c
- sei();
- // TWI initialisieren
- i2c_init();
- /*
- MAX7219_Init();
- MAX7219_Clear();
- MAX7219_Write(1, 0x5A);
- */
- // LCD initialisieren
- lcd_init();
- // LCD-Anzeige loeschen
- lcd_command(LCD_CLEAR);
- // Hintergrundbeleuchtung an
- lcd_backlight(ON);
- PCF8574_Init(LCD_PCF8574_ADR_PREFIX); //LCD
- PCF8574_Init(PORTEXPANDER_PCF8574_ADR_PREFIX); //LEDLEISTE
- // Text auf LCD ausgeben
- // MIT RAM , als falsch
- strcpy_P( gcaStr, PSTR("* I2C LCD *") );
- lcd_printlc(1,1,(unsigned char *)gcaStr);
- strcpy_P( gcaStr, PSTR("*Christof Ermer*"));
- lcd_printlc(2,1,(unsigned char *)gcaStr);
- CRLF();uart_puts_p( PSTR( DATUM ) );
- CRLF();uart_puts_p( PSTR( SOFTWARE ) );
- CRLF();uart_puts_p( PSTR( HARDWARE ) );
- CRLF();uart_puts_p( PSTR( AUTOR ) );
- //MAX7219_Clear();
- // TickCounter Starten
- TCNT0 = 0;
- OCR0A = 250;
- TCCR0A = (1<< WGM01) ; //CTC
- TIMSK0 = (1<< OCIE0A); //INT
- //TIMSK0 = (1<< TOIE0); //Aktiviert Int0 OVL Interrupt
- TCCR0B = (1<< CS02); //256
- sei();
- #ifdef USE_T2_AUToPRESCALER
- TCNT2=0;
- DDRB |= (1<<PB3);
- //OCRx = Quarz / Vorteiler / gewünschte Frequenz
- SelectBestPreScaler_T2( gfSollFRQ );
- TCCR2A= (1<< COM2A0) | (1<< WGM21); //Toogle OC2A FEHLER IN PDF
- sei();
- #endif
- #ifdef USE_T1_AUToPRESCALER
- TCNT1=0;
- DDRB |= (1<<PB1);
- //OCRx = Quarz / Vorteiler / gewünschte Frequenz
- SelectBestPreScaler_T1( gfSollFRQ );
- TCCR1A= (1<< COM1A0); // Toogle OC1A
- sei();
- #endif
- Start_Clock();
- wdt_reset(); //WATCHDOG!
- uart_puts_p( PSTR("\r\nDCF77 Clock org.by Ulrich Radig, modification by. Christof Ermer - Regensburg\r\n") );
- wdt_reset(); //WATCHDOG!
- SET_INTLED();
- Plip( BEEP_LONG_MS );
- for(;;)
- {
- sei();
- wdt_reset(); //WATCHDOG!
- u32CPULoops++;
- i2c_start_wait( PORTEXPANDER_PCF8574_ADR_PREFIX + I2C_WRITE );
- i2c_write( gu8DCF_Status ); // If( 2c_write( ........
- i2c_stop();
- if( gu8ProgStatusFlags & STATUS_DAC_EVENT )
- {
- gu8ProgStatusFlags &= ~STATUS_DAC_EVENT;
- u16DAC = 2047 + 2046 * sin ( 2* M_PI * (u16DAC_Cnt/2048.0) );
- u16DAC_Cnt++;
- u16DAC_Cnt %= 2048;
- LT2157(u16DAC);
- };
- // --------------------------------------------------------------------
- if( gstDCF_Flags.dcf_NoSignal )
- {
- gu8DCF_Status ^= 0xFF; // bkinke wie blöd
- };
- if( gstDCF_Flags.dcf_SecPuls )
- {
- gstDCF_Flags.dcf_SecPuls = 0;
- TOGGLE_INTLED(); // 1,0HZ
- Plip( BEEP_KNACKS_MS );
- };
- if( gstDCF_Flags.dcf_Plip )
- {
- gstDCF_Flags.dcf_Plip = 0;
- Plip( BEEP_KNACKS_MS );
- TOGGLE_INTLED(); // 1,0HZ
- };
- if( gstDCF_Flags.dcf_Beep )
- {
- gstDCF_Flags.dcf_Beep= 0;
- Plip( BEEP_SHORT_MS); //Piepser oder so
- //BEEP_PAUSE
- };
- if( gstDCF_Flags.dcf_BeepLong )
- {
- gstDCF_Flags.dcf_BeepLong = 0;
- Plip( BEEP_LONG_MS ); //Piepser oder so
- };
- if( gu8DCF_Status & DCF_Sec_Puls )
- {
- gu8DCF_Status &= ~DCF_Sec_Puls;
- };
- // --------------------------------------------------------------------
- //Toggle_Bit(1);
- if( gu8ProgStatusFlags & STATUS_TICK_EVENT )
- {
- gu8ProgStatusFlags &= ~STATUS_TICK_EVENT;
- //TOGGLE_INTLED();
- if( gstDCF_Flags.dcf_NoSignal )
- {
- uart_puts_p( PSTR("\r\n\t ** NO DCF SIGNAL ***") );
- };
- CRLF();
- CRLF();
- uart_puts_p( PSTR("MCU:") );
- ultoa( u32CPULoops, gcaNumStr, 10 );
- u32CPULoops=0;
- uart_puts( gcaNumStr );
- uart_puts_p( PSTR("\tFrq:") );
- FloatToNumStr(gfSollFRQ);
- uart_puts( gcaNumStr );
- CRLF();
- uart_puts_p( PSTR("gu16Pulsweite:") );
- ultoa( gu16Pulsweite, gcaNumStr, 10 );
- uart_puts( gcaNumStr );
- CRLF();
- uart_puts_p( PSTR("gu32DCF_msTimerSync:") );
- ultoa( gu32DCF_msTimerSync, gcaNumStr, 10 );
- uart_puts( gcaNumStr );
- CRLF();
- sprintf(gcaStr, "\t DMY:%02d-%02d-%02d Time: %02d:%02d:%02d \tSync:%d \tRx:%d", //%i
- day,mon,year,hh,mm,ss, gstDCF_Flags.dcf_sync, gstDCF_Flags.dcf_rx);
- uart_puts( gcaStr );
- CRLF();
- uart_puts_p( PSTR("DCF:") );
- uart_puts( U64ToBin( gstunDCF77_Bits.u64DCF_RxBuffer ) );
- CRLF();
- uart_puts_p( PSTR("DCFstat:") );
- uart_puts( ByteToBin( gu8DCF_Status ) );
- uart_puts_p( PSTR("\tRxCnt:") );
- uart_puts( ULongToNumStr( gu8Rx_BitCnt ) );
- CRLF();
- uart_puts_p( PSTR("DCF_FLAGS_") );
- u8NN |= (gstDCF_Flags.parity_err << 0);
- u8NN |= (gstDCF_Flags.parity_P1 << 1);
- u8NN |= (gstDCF_Flags.parity_P2 << 2);
- u8NN |= (gstDCF_Flags.parity_P3 << 3);
- u8NN |= (gstDCF_Flags.dcf_rx << 4);
- u8NN |= (gstDCF_Flags.dcf_sync << 5);
- u8NN |= (gstDCF_Flags.dcf_NoSignal << 6);
- u8NN |= (gstDCF_Flags.dcf_SecPuls << 7);
- uart_puts( ByteToBin( u8NN ) );
- CRLF();
- uart_puts_p( PSTR("Weather_1: ") );
- uart_puts( WordToBin( gu16aWeatherSeq[0] ) );
- uart_puts_p( PSTR("\tWeather_2: ") );
- uart_puts( WordToBin( gu16aWeatherSeq[1] ) );
- uart_puts_p( PSTR("\tWeather_3: ") );
- uart_puts( WordToBin( gu16aWeatherSeq[2] ) );
- CRLF();
- uart_puts_p( PSTR("\tWeather_64:") );
- uart_puts( U64ToBin( gu64Weather ) );
- CRLF();
- uart_puts_p( PSTR("Weather_5Byte: ") );
- uart_puts_p( PSTR("\tW5: ") );
- uart_puts( ByteToBin(gu8aWeatherData[4]) );
- uart_puts_p( PSTR("\tW4: ") );
- uart_puts( ByteToBin(gu8aWeatherData[3]) );
- uart_puts_p( PSTR("\tW3: ") );
- uart_puts( ByteToBin(gu8aWeatherData[2]) );
- uart_puts_p( PSTR("\tW2: ") );
- uart_puts( ByteToBin(gu8aWeatherData[1]) );
- uart_puts_p( PSTR("\tW1: ") );
- uart_puts( ByteToBin(gu8aWeatherData[0]) );
- /// LCD ** LCD ** LCD ** LCD ** LCD ** LCD ** LCD ** LCD ** LCD ** LCD **
- lcd_command(LCD_CLEAR);
- sprintf(gcaStr, "%02d:%02d:%02d",hh,mm,ss );
- strcat_P( gcaStr, PSTR(" ") );
- FloatToNumStr(gfSollFRQ);
- strcat( gcaStr, gcaNumStr);
- *(gcaStr+16) = 0;
- lcd_printlc(1, 1, (unsigned char *)gcaStr );
- //utoa(year,gcaNumStr,10);
- sprintf(gcaStr, "%02d.%02d.%02d",day,mon,year);
- strcat_P( gcaStr, PSTR(" B") );
- ultoa( gu8Rx_BitCnt, gcaNumStr, 10 );
- strcat( gcaStr, gcaNumStr);
- strcat_P( gcaStr, PSTR(" S") );
- ultoa( gstDCF_Flags.dcf_sync, gcaNumStr, 10 );
- strcat( gcaStr, gcaNumStr);
- *(gcaStr+16)=0;
- lcd_printlc(2, 1, (unsigned char *)gcaStr);//lcd_printlc(2,1,(unsigned char *)gcaStr);
- /*
- strcat_P(gcaStr, PSTR(" S:") );
- ultoa( u16DAC, gcaNumStr, 10 );
- strcat( gcaStr, gcaNumStr);
- */
- //strcpy_P( gcaStr, PSTR("* I2C LCD *") );
- }; //TICK
- if( gu8BefehleFlags & BEFEHLE_ORDER_FLAG )
- {
- CheckOrder();//gcaRxStr = accumulated str
- ResetRxBuff();
- };
- //CLR_INTLED();
- }; //for
- }; // main
- ====================================================================
- ServiceFunc.c + HEADER
- =================================
- // HEADER
- #ifndef SERVICCE_FUNC_HEADER
- #define SERVICCE_FUNC_HEADER
- // ==================================================
- #define USE_SPRINT_CONV
- #define USE_NUM_TO_STR_FUNC
- #define USE_T1_AUToPRESCALER
- // ==================================================
- // ------------------------------------------------------
- #ifdef USE_MAX543
- #define MAX543DDRX DDRB
- #define MAX543PORTX PORTB
- #define MAX543CLK_BIT 0x02 //1
- #define MAX543SRI_BIT 0x04 //2
- #define MAX543LOAD_BIT 0x08 //3
- #define MAX543_CLK_HIGH() (MAX543PORTX |= MAX543CLK_BIT)
- #define MAX543_CLK_LOW() (MAX543PORTX &= ~MAX543CLK_BIT)
- #define MAX543_SRI_HIGH() (MAX543PORTX |= MAX543SRI_BIT)
- #define MAX543_SRI_LOW() (MAX543PORTX &= ~MAX543SRI_BIT)
- #define MAX543_LOAD_HIGH() (MAX543PORTX |= MAX543LOAD_BIT)
- #define MAX543_LOAD_LOW() (MAX543PORTX &= ~MAX543LOAD_BIT)
- #define SET_MAX543_INIT() (MAX543DDRX |= MAX543CLK_BIT | MAX543SRI_BIT | MAX543LOAD_BIT)
- #define DEL2CYCLES() __asm__ __volatile__( "rjmp 1f\n 1:" );
- extern void MAX543( uint16_t u16Val );
- #endif
- // ------------------------------------------------------
- #ifdef USE_LEDSHOWBYTE
- #define Bit0_5_DDRX DDRC
- #define Bit6_7_DDRX DDRD
- #define Bit0_5_PORT DDRC
- #define Bit6_7_PORT PORTD
- #define Bit0_5_MSK 0b00111111
- #define Bit6_7_MSK 0b11000000
- extern void LEDShowByte( uint8_t u8Byte );
- #endif
- // ------------------------------------------------------
- #ifdef USE_ADC
- extern uint16_t ADC_10Bit(uint8_t u8Chan);
- #endif
- // ------------------------------------------------------
- #ifdef USE_PWM_T2
- extern void ServoPWM_T2_Init(void);
- #endif
- // ------------------------------------------------------
- #ifdef USE_T1_AUToPRESCALER
- extern void SelectBestPreScaler_T1( float fSollFrq );
- #endif
- // ------------------------------------------------------
- #ifdef USE_T2_AUToPRESCALER
- extern void SelectBestPreScaler_T2( float fSollFrq );
- #endif
- #ifdef USE_NUM_TO_STR_FUNC
- #define FLOAT_PRAEDIGITS_MAX 5
- #define FLOAT_DIGITS_MAX 1 // DIgits nach //dtostrf(fVal,NUMMAX, DIGITS_MAX, gcaNumStr);
- extern char* FloatToNumStr(double fVal);
- extern char* LongToNumStr(int32_t lVal);
- extern char* ULongToNumStr(uint32_t ulVal);
- #endif
- #ifdef USE_SPRINT_CONV
- extern void SLongToNumStr(int32_t lVal);
- extern void SFloatToNumStr(double fVal);
- #endif
- #endif // SERVICE_FUNC_HEADER
- ==================================================
- Service.c
- ==================================================
- //------------------------------------------------------------------------------
- // Programmed by Christof Ermer 12.2019
- //------------------------------------------------------------------------------
- #include "main.h"
- #include "ServiceFunc.h"
- //MAX7219_Write(1, gu8Morse_Flags_Rx );
- #ifdef USE_SPRINT_CONV
- // **********************************************
- void SLongToNumStr(int32_t lVal)
- // **********************************************
- {
- sprintf(gcaNumStr,"%ld", lVal); //Ulong = %ld
- };
- // **********************************************
- void SFloatToNumStr(double fVal)
- // *************
- {
- sprintf(gcaNumStr,"%.1f", fVal);
- };
- #endif
- #ifdef USE_NUM_TO_STR_FUNC
- // **********************************************
- char* FloatToNumStr(double fVal)
- // *************
- {
- dtostrf(fVal, FLOAT_PRAEDIGITS_MAX, FLOAT_DIGITS_MAX, gcaNumStr ); //[-]d.ddd
- return gcaNumStr;
- };
- // **********************************************
- char* LongToNumStr(int32_t lVal)
- // **********************************************
- {
- ltoa(lVal, gcaNumStr, 10 );
- return gcaNumStr;
- };
- // **********************************************
- char* ULongToNumStr(uint32_t ulVal)
- // **********************************************
- {
- ultoa(ulVal, gcaNumStr, 10 );
- return gcaNumStr;
- };
- #endif
- #ifdef USE_T2_AUToPRESCALER
- // ********************************************
- void SelectBestPreScaler_T2( float fSollFrq )
- // ********************************************
- {
- fSollFrq*= 2; // Toogle = / 2
- if( (F_CPU / 1 / fSollFrq ) > 0xFF)
- {
- if( (F_CPU / 8 / fSollFrq ) > 0xFF)
- {
- if( (F_CPU / 32 / fSollFrq ) > 0xFF)
- {
- if( (F_CPU / 64 / fSollFrq ) > 0xFF)
- {
- if( (F_CPU / 128 / fSollFrq ) > 0xFF)
- {
- if( (F_CPU / 256 / fSollFrq ) > 0xFF)
- {
- TCCR2B = (1<< CS22) | (1<< CS21) | (1<< CS20); //CTC 1024
- OCR2A = round (F_CPU / 1024 / fSollFrq);
- }
- else
- {
- TCCR2B = (1<< CS22) | (1<< CS21); //CTC 256
- OCR2A = round (F_CPU / 256 / fSollFrq);
- };
- }
- else
- {
- TCCR2B = (1<< CS22) | (1<< CS20); //CTC 128
- OCR2A = round (F_CPU / 128 / fSollFrq);
- };
- }
- else
- {
- TCCR2B = (1<< CS22); //CTC 64
- OCR2A = round (F_CPU / 64 / fSollFrq);
- };
- }
- else
- {
- TCCR2B = (1<< CS21)| (1<< CS20); //CTC 32
- OCR2A = round (F_CPU / 32 / fSollFrq);
- };
- }
- else
- {
- TCCR2B = (1<< CS21); //CTC 8
- OCR2A = round (F_CPU / 8 / fSollFrq);
- }
- }
- else
- {
- TCCR2B = (1<< CS20); //CTC 1
- OCR2A = round (F_CPU / fSollFrq); // /1
- };
- };
- #endif
- #ifdef USE_T1_AUToPRESCALER
- // ********************************************
- void SelectBestPreScaler_T1( float fSollFrq )
- // ********************************************
- {
- fSollFrq*= 2; // Toogle = / 2
- if( (F_CPU / 1 / fSollFrq ) > 0xFFFF)
- {
- if( (F_CPU / 8 / fSollFrq ) > 0xFFFF)
- {
- if( (F_CPU / 64 / fSollFrq ) > 0xFFFF)
- {
- if( (F_CPU / 256 / fSollFrq ) > 0xFFFF)
- {
- TCCR1B = (1<< WGM12) | (1<<CS12) | (1<< CS10); //CTC 1024
- OCR1A = round (F_CPU / 1024 / fSollFrq);
- }
- else
- {
- TCCR1B = (1<< WGM12) | (1<<CS12); //CTC 256
- OCR1A = round (F_CPU / 256 / fSollFrq);
- };
- }
- else
- {
- TCCR1B = (1<< WGM12) | (1<<CS11) | (1<<CS10); //CTC 64
- OCR1A = round (F_CPU / 64 / fSollFrq);
- };
- }
- else
- {
- TCCR1B = (1<< WGM12) | (1<<CS11); //CTC 8
- OCR1A = round (F_CPU / 8 / fSollFrq);
- };
- }
- else
- {
- TCCR1B = (1<< WGM12) | (1<<CS10); //CTC 1
- OCR1A = round (F_CPU / fSollFrq); // /1
- };
- };
- #endif
- #ifdef USE_MAX543
- // ******************************
- void MAX543( uint16_t u16Val )
- // ******************************
- {
- Toggle_Bit(1);
- uint8_t u8NN=11;
- SET_MAX543_INIT();
- MAX543_CLK_LOW(); //Startcondition
- MAX543_LOAD_HIGH(); //Startcondition
- do
- {
- if( u16Val & (1 << u8NN) )
- {
- MAX543_SRI_HIGH();
- }
- else
- {
- MAX543_SRI_LOW();
- };
- _delay_us(1);
- MAX543_CLK_HIGH();
- _delay_us(1);
- MAX543_CLK_LOW();
- }while( u8NN-- );
- MAX543_LOAD_LOW();
- };
- #endif
- #ifdef USE_PWM_T2
- // ***************************
- void ServoPWM_T2_Init(void)
- // ***************************
- {
- DDRB |= SERVO_T2_PWM_BIT;
- //F_CPU / 1024 / 256--> 61Hz = 16.384 mSekunden/Periode bei 256erTeilung
- // 1MS --> 256 / 16.384 = 15.625 ~16
- OCR2A = PM1MS; //20ms-_> 256/20 = 12.8
- TCCR2A = _BV(WGM21) | _BV(WGM20) | _BV(COM2A1); // FAST PWM / Clear by Match
- TCCR2B =_BV(CS22) | _BV(CS21) | _BV(CS20); // x07 setzt / 1024
- };
- #endif
- #ifdef USE_LEDSHOWBYTE
- // *************************************
- void LEDShowByte( uint8_t u8Byte )
- // *************************************
- {
- Bit0_5_DDRX |= Bit0_5_MSK;
- Bit6_7_DDRX |= Bit6_7_MSK;
- Bit0_5_PORT = (Bit0_5_PORT & ~ Bit0_5_MSK) | (u8Byte & Bit0_5_MSK);
- Bit6_7_PORT = (Bit6_7_PORT & ~ Bit6_7_MSK) | (u8Byte & Bit6_7_MSK);
- };
- #endif
- #ifdef USE_ADC
- /*
- ADC_INTERN-----ADC_INTERN-----ADC_INTERN---ADC_INTERN
- ADC_EXTERNREF_USED_ENABLED
- PRESCALER 3,6864 / 32 = 115200 50-200Khz gewünscht
- REM ADC4-ADC5 = 8 BIT;
- 4+2 Channel.
- */
- //****************************************************************
- uint16_t ADC_10Bit(uint8_t u8Chan)
- //****************************************************************
- {
- DDRC &= ~ _BV(u8Chan); //port A Chanel Bit Input
- PORTC &= ~ _BV(u8Chan); //Wegen Pullup abschalten
- // Activate ADC with Prescaler 16 --> 16Mhz/128 = 125 khz
- ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) |_BV(ADPS0);
- // Select pin ADC0 using MUX
- ADMUX = (1 << REFS0) | u8Chan; //Interne VCC + 100nF an AREF, KEIN VCC an AREF
- //Start conversion
- ADCSRA |= _BV(ADSC);
- while( ADCSRA & _BV(ADSC) ) // wait until conversion completed
- {
- wdt_reset();
- };
- return ADC;// get converted value
- };
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement