wiki:examples:dcf77_radio-clock_decoder
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
wiki:examples:dcf77_radio-clock_decoder [2015/11/28 14:52] – pmueller | wiki:examples:dcf77_radio-clock_decoder [2023/01/21 16:42] (current) – [Conclusion] webmin | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== | ====== | ||
- | In this example a decoder for the DCF77 standard-frequency radio signal is presented. The transmitter is located nearby Frankfurt in Germany and continuously transmits a 77.5 kHz signal that encodes the local time using amplitude and phase modulation. The sender is controlled by the high-precision atomic clocks | + | In this example a decoder for the DCF77 standard-frequency radio signal is realised based on two cooperating state machines. You will learn how to use the features |
+ | * Machines based on conditional | ||
+ | * Adding own variables to the machine instance data | ||
+ | * Adding own code to the generated state machine file | ||
+ | * Using an own event type that includes | ||
- | {{ : | ||
- | ==== Task of the state-machine | + | ==== DCF77 Basics |
+ | The transmitter is located nearby Frankfurt in Germany and continuously transmits a 77.5 kHz signal that encodes the local time using amplitude and phase modulation. The sender is controlled by the high-precision atomic clocks of the German institute of standards ([[http:// | ||
- | The DCF-77 modulation reduces the signal amplitude for 0.1 seconds (short pulse, 0-bit) or 0.2 seconds (long pulse, 1-bit) at the beginning of each second, allowing to transmit 1 bit of data per second. A simple BCD-encoding scheme is used to transmit the hours, minutes, days, and data information for the next following minute. To allow synchronization into the signal, no pulse is send during the 59th second, so that the start of the next pulse exactly marks the beginning of the minute. | + | {{ : |
- | The following state machine decodes the received pulses and calles setClock() if the clock/date information was successfully received. | + | |
- | {{ :wiki: | + | The DCF-77 modulation reduces the signal amplitude for 0.1 seconds (short pulse, 0-bit) or 0.2 seconds (long pulse, 1-bit) at the beginning of each second, allowing to transmit 1 bit of data per second. A simple BCD-encoding scheme is used to transmit the hours, minutes, days, and data information for the next following minute. Encoding scheme of the time information transmitted with DCF77 is presented [[https://www.ptb.de/ |
- | The software runs on a MSP430-1232 evaluation board and can be compiled with the IAR KickStart Editon for MSP430. The CPU is normally in low power mode and wakes up about every 5ms triggered from a timer interrupt. Within this timer interrupt the pulse width is measured. If a pulse was detected the state machine is called with event evTick. If the pulse length does not fit the defined limits an evTimingError event is sent. At the end setClock() gets called e.g. to display the time/date on a LCD display. | + | {{ : |
- | The complete source code and model file is part of the Sinelabore [[wiki: | + | To allow synchronization into the continuously sent signal, no pulse is send during the 59th second, so that the start of the next pulse exactly marks the beginning |
- | ~~DISCUSSION|Leave your comments~~ | + | The receiver application was splitted into two separate state machines. |
+ | |||
+ | ==== The pulse detection state machine ==== | ||
+ | The pulse detection state machine runs within a cyclic | ||
+ | |||
+ | The CPU is normally in low-power state. But when a pulse or minute start is detected the decoder machine and wakes up the CPU. | ||
+ | |||
+ | <code c> | ||
+ | #pragma vector=TIMERA0_VECTOR | ||
+ | __interrupt void Timer_A0(void){ | ||
+ | |||
+ | // set debug output high if pin of dcf77 signal is high | ||
+ | if((P1IN & 0x01) == 1U) P1OUT |= 0x04; | ||
+ | else P1OUT & | ||
+ | |||
+ | P1OUT |= 0x08; // set debug len of irq | ||
+ | |||
+ | dcf77_irq(& | ||
+ | if(irqSM.msg==evTick || irqSM.msg==evMinStart){ | ||
+ | // wake up main CPU, got valid pulse | ||
+ | __bic_SR_register_on_exit(LPM3_bits); | ||
+ | } | ||
+ | |||
+ | P1OUT & | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The state machine was created with the integrated state diagram editor. A screenshot is shown here. The editor allows to create state machine diagrams in very efficient way. A multipart [[wiki: | ||
+ | |||
+ | {{: | ||
+ | |||
+ | The state diagram editor allows to directly add code to various sections of the state machine. In this example some helper functions and variables were added to the begin of the state machine file. More details about the offered possibilities can be found in the [[wiki: | ||
+ | |||
+ | |||
+ | ==== The decoder state machine ==== | ||
+ | |||
+ | The second state machine runs in the endless main loop and executes once if a pulse was detected. Initially it waits for the minute begin. Once found the state machine processes the events coming from the pulse detection machine (in opposite to the above conditional state machine). The first 20 bits contain special information and are ignored. Then once the minutes bits come the time and date information is captured and decoded. And finally the clock is set before the cycle starts again. | ||
+ | {{wiki: | ||
+ | |||
+ | The following code shows the main loop which only runs if a new pulse is available for processing. | ||
+ | The state machine uses an own event type (see below) which is filled before the machine is called. | ||
+ | Then the low power mode is entered again. | ||
+ | |||
+ | <code c> | ||
+ | while(1) { | ||
+ | _BIS_SR(LPM3_bits + GIE); // Enter LPM3 | ||
+ | __no_operation(); | ||
+ | |||
+ | P3OUT |= 0x8; // set D2 debug output | ||
+ | |||
+ | // update event information and call the decoder | ||
+ | decoderEvt.msg = irqSM.msg; | ||
+ | decoderEvt.len = irqSM.len; | ||
+ | decoder(& | ||
+ | |||
+ | P3OUT & | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== Event Type ==== | ||
+ | This example presents another feature of the code generator. The state machine handler can have different signatures. Usually a pointer to the instance data and the event to process, is handed over. Here we have defined an own event type (OWN_DECODER_EVENT_T) which contains not just the event but also some data (the length of the detected pulse). | ||
+ | |||
+ | For this state machine handler signature: | ||
+ | <code c> | ||
+ | void decoder(DECODER_INSTANCEDATA_T *instanceVar, | ||
+ | </ | ||
+ | |||
+ | the following parameters must be set in the configuration file. Note: the integrated editor has as helper function to find the right parameters for you (Code-> | ||
+ | |||
+ | < | ||
+ | UseInstancePointer=yes | ||
+ | HsmFunctionWithEventParameter=yes | ||
+ | InlineChangeToStateCode=yes | ||
+ | HsmFunctionUserDefinedEventParameter=OWN_DECODER_EVENT_T | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== Debugging Trace ==== | ||
+ | To better understand the timing of the design some debug signals are generated in the irq handler and the main loop. The following figure shows {{ : | ||
+ | |||
+ | ==== Organization of the Code ==== | ||
+ | Each state machine is in its own folder. Within each folder you will find the state machine model file (*.xml) and the corresponding configuration file. You can open and edit the files easily using the state machine executable (right-click on the file and open with sinelabore.exe). In the tool you can then regenerate the code in the case you made changes. In '' | ||
+ | |||
+ | |||
+ | ==== Conclusion ==== | ||
+ | This tutorial presented how to use conditional and event based state machines to realise a complete application on a small embedded system. The whole code fits in 2kB of code and 110 bytes of ram. | ||
+ | |||
+ | The complete source code and model files are {{ : | ||
{{tag> | {{tag> | ||
+ | |||
+ |
wiki/examples/dcf77_radio-clock_decoder.1448718752.txt.gz · Last modified: 2015/11/28 14:52 by pmueller