.. _clockworks: ============= Clock Works ============= :Author: Erich Wälde :Contact: amforth-devel@lists.sourceforge.net :Date: 2018-12-15 :License: CC BY-NC-SA .. contents:: :local: :depth: 1 Intro ===== This is the top page of a project, which deals with clocks. However, this project did happily explode into a large collection of fun projects, too many to do them all. Instead of giving up, I decided to do a series of documentation units, starting with the bare minimum and adding optional units to cover other things. If you speak or read German: a lot of this material has been covered in the journal "Vierte Dimension" of "Forth Gesellschaft e.V." available at https://www.forth-ev.de and https://wiki.forth-ev.de/doku.php/vd-archiv starting 2016-04 and references therein. There is a corresponding page for some source code and pointers in the wiki as well, see https://wiki.forth-ev.de/doku.php/projects:clockworks:clockworks Warning ======= Let's be very clear about this: **Noone needs yet another clock!** --- there are way too many of them already dictating our course during the day. But if you decide to ignore this warning and try to make your own nonetheless, you will enter a whole new world of little wonders, fantastic sights, and incredible creativity. Welcome to the world of AmForth on atmega microcontrollers, time, and clocks. Have the appropriate amount of fun! License ======= **AmForth** is licensed under GPLv3 (since version 5.6), and GPLv2 before. **This documentation** is licensed under `CC-BY-NC-SA (Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License) <http://creativecommons.org/licenses/by-nc-sa/4.0/>`_. This documentation is not part of AmForth, allthough it is kindly hosted here. The **example code** (even when included in the documentation) is placed under the `CC0 (Creative Commons Zero License, 1.0 unported) <http://creativecommons.org/publicdomain/zero/1.0/>`_. This should be equivalent to placing the example code directly in the public domain, worldwide! What can you do with the example code? #. You can take the example code, verbatim or modified, and run it on a device of your choice. #. You can use the example code to create your own project. #. You can give the example code verbatim or modified to your neighbour, or better still, point your neighbour to this project. #. However, when you give the example code to anyone else **in compiled form** (think programmed controller using AmForth), then the distribution obligations of the license for *AmForth* come in: be sure to provide the code of the AmForth system, the used example code, your modifications --- all in source form (the preferred representation for modification, gpl v3 section 1). If you cannot do this for whatever reason, AmForth is not a possible choice for your project. *Explanation:* compiling Forth code extends the Forth system in use. In compiled form, neither can the newly compiled functions (aka words) be used as an independant entity, nor are new words distinguishable from the words of the original Forth system in any way. Thus compiled Forth code always creates a *derived works* of the underlying Forth system, including its license. There are no exceptions. #. When you reuse the example code for some other Forth/language, then the license of the example code would have to be respected. Thus I would like to place the example code voluntarily in the public domain. Apparently I cannot legally do so in my jurisdiction, so I have to resort to `CC0 (Creative Commons Zero License, 1.0 unported) <http://creativecommons.org/publicdomain/zero/1.0/>`_. If you find a bug in the example code, or if you think the documentation should be enhanced or corrected, I'm happy to receive a report. If you find this documentation useful, or if you use the example code for your project, I would be very interested to hear about it. If you use AmForth, please consider contributing a link for the *Commented Projects* Section. Setup of Hardware ================= The code presented here was developed and tested on an atmega-644p controller. The AmForth system (version 6.5 at the time of writing) has been derived from the files in ``appl/template/``. The only changes in ``template.asm`` were the frequency of the main crystal (``.equ F_CPU = 11059200``), the baud rate (``.set BAUD=115200``), and as a matter of personal preference ``.set WANT_IGNORECASE = 0``. The first two you typically have to adjust for your project anyway. The example code should work without the third change, however, I did not test this. Allthough care has been taken and allthough the shown schematics work for the author himself, the author does not garantee the shown schematics to work under any conditions. You have to verify that things work for you. Do not burn your house! .. _clockworks_ingredients: Ingredients and Clocks ====================== A microcontroller driven clock needs some means to produce a periodic event, e.g. a timer overflow interrupt at some known frequency. This represents the smallest meaningful unit of time on this system, let's call this a *tick*. These *ticks* are counted to measure a *second*, which in turn are counted to measure a *minute* and so forth. Add some means to display the values of said counters and we do have a minimal clock. While this clock is definitely rather lacking in several respects, we already run into a lengthy list of options regarding its implementation. We have to make choices before the first line of code is written. * :doc:`Generating Ticks from the main crystal <01_ticks_main_crystal>` --- this option is readily available without any additional hardware. * **OR** :doc:`Generating Ticks from an additional clock crystal <01_ticks_clock_crystal>` --- this option needs an extra crystal and possibly tiny load capacitors. However, it enables the possibility to make the controller go to sleep between ticks. * **OR** :doc:`Generating Ticks from an external clock source <01_ticks_external>` --- using an external clock source might provide greater long term accuracy, e.g. by using a TCXO (*temperature compensated crystal oscillator*) or a pps pin of a GPS unit. * :doc:`Keeping Track of Time <02_keeping_track>` using common counters (sec, min, hour, ...) --- while these counters are very common, they are not strictly neccessary. There could be other means to extract the common time format from some counter (seconds of the day, e.g.). * :doc:`Periodic Jobs <03_periodic_jobs>` --- I have implemented various parts of the clock using jobs (simple functions, really) which are called periodically. While this is kind of an obvious solution, it is not strictly neccessary. * :doc:`Multitasking <04_multitasking>` --- execute ``run-loop`` in the background. Not strictly neccessary. * :doc:`Display <20_display_top>` --- to see the whole thing work Model 1: The Fairly Minimal Clock --------------------------------- :doc:`Model 1 <40_main_fairly_minimal>` needs one version of clock ticks, keeping track of time, the periodic jobs plus some means to display its counters representing the time, in other words: a main program to make the whole magic work. ------------------------------------------------------------------- .. * :doc:`Adding a RTC (battery backed) <06_rtc>` --- if we want to keep time over a power outage, we better have one of these! * :doc:`Accessing Shift Registers <07_shift_register>` --- accessing LEDs and 7-segment digits without the flicker * :doc:`Abakus display <21_display_abakus>` --- even more geek than binary? Model 2: The Abakus Clock ------------------------- :doc:`Model 2 <41_main_clock_abakus>` features a unique display and also a battery backed real time clock to keep correct time across power outage. ------------------------------------------------------------------- .. * :doc:`7-Segment LED Digits <22_display_7segment_digits>` --- a display with four digits. Could be expanded! * :doc:`Unix Epoch Seconds <05_epochseconds>` --- in order to implement time zones I decided to use epoch seconds. They implement another software clock. * :doc:`Time Zones <08_timezones>` --- want to display local time rather than UTC? This is the way to go. Model 3: The UTC Wall-Clock --------------------------- :doc:`Model 3 <42_main_utc_wall_clock>` features four 7-segment digits as a display, however, they are large (70mm high) to make them readable across the room. The concept of time zones has been added, so daylight savings time is only flipping a switch away. ------------------------------------------------------------------- .. * :doc:`Small improvements for readable code <09_small_improvements>` --- there are a lot of functions available to write your code more concise. * :doc:`Changing the prompt / StationID <10_prompt_ready>` --- we add a station ID to the code running on every board and display its value in the prompt. Because we can! * :doc:`Managing several sets of clock counters <11_clocks>` --- using ``structures`` will ease book keeping. Along the way we add labels for time zones. And we can run several such `clocks` in parallel, if needed. * :doc:`Calculating the length of a month <11_lastday_of_month>` in the Gregorian Calendar might be useful in its own right, so factored it. * :doc:`Keeping Track of Time revisited <02_keeping_track_2>` --- cleaning up the remaining code while using `clocks`. * :doc:`Creating a persisten jump table <11_persistent_jump_table>` --- this is a technique I have used in other places. The content of the jump table is calculated at compile time (in RAM) and then preserved in flash memory. * :doc:`Reading a dcf77 receiver <12_reading_dcf77>` --- this turns out to be quite complex and requires a lengthy chunk of code. Model 4: The DCF77 controlled UTC Wall-Clock -------------------------------------------- :doc:`Model 4 <43_main_utc_dcf77_wall_clock>` is Model 3 but with a large software addition: the time is read from a DCF77 receiver and periodically synchronised to the microcontrollers counters, and optionally to the attached RTC. Another warning: DCF77 is a central-european facility. There are alternatives elswehere on the planet, consult `wikipedia Radio Clock <https://en.wikipedia.org/wiki/Radio_clock>`_ for a list. ------------------------------------------------------------------- More Stuff to come ================== * phase accumulator to compensate a frequency offset in ticks * Multitasker and simultaneous access on serial interface * Conversion to Unix Epoch Seconds :ref:`epoch_seconds` * Long term accuracy * Displays, also fancy ones This represents the visible part of the clock. Given diverse preferences amongst people, this is the most creative area of clock projects. I urge you to spend an afternoon looking at all the fancy clock designs, that can be found on the world wide web! This list cannot be complete ever, not even in categories: * serial interface * some LCDisplay --- this is a common choice * LEDs of 7Segment-Digits, multiplexed in some way. * Did I mention that I hate multiplexed displays? It hurts my eyes, so please use shift-registers and do away with multiplex blinking! * analog type displays * audio *display* for the vision impaired, or just because we can * Time Zones, Daylight Savings Time * Other Time Scales * Epoch seconds * siderial time * swatch beats * Alarm Clock The Things Side =============== While dealing with such a project, once in a while a number of things must be relearned the hard way. Afterwards they are obvious, however, while in the (code--)jungle they are not funny at all. On the other hand, what would the world be if noone had to tell stupid stories ... * Cables --- There exists a subtle variation of `"is the cable connected?"`: Never underestimate the possibility to have more than one broken cable at the same time. References ========== * `wikipedia: List of calendars <https://en.wikipedia.org/wiki/List_of_calendars>`_ * `wikipedia: Gregorian Calendar <https://en.wikipedia.org/wiki/Gregorian_calendar>`_ * `wikipedia: Leap year <https://en.wikipedia.org/wiki/Leap_year>`_ * `wikipedia: Leap second <https://en.wikipedia.org/wiki/Leap_second>`_ * `wikipedia: Time zone <https://en.wikipedia.org/wiki/Time_zone>`_ * `wikipedia: Daylight saving time <https://en.wikipedia.org/wiki/Daylight_saving_time>`_ * `wikipedia: Julian Day <https://en.wikipedia.org/wiki/Julian_day>`_ * `wikipedia Radio Clock <https://en.wikipedia.org/wiki/Radio_clock>`_ * `Unix Time (aka Epoch Seconds) <https://en.wikipedia.org/wiki/Unix_time>`_ * `The Year 2038 Problem <https://en.wikipedia.org/wiki/Year_2038_problem>`_ * `wikipedia: Abacus <https://en.wikipedia.org/wiki/Abacus>`_ Changes ======= * *2017-10-01* initial release * *2018-12-15* added Model 4 (UTC DCF77 clock) Included Docs ============= .. toctree:: :maxdepth: 1 01_ticks_main_crystal.rst 01_ticks_clock_crystal.rst 01_ticks_external.rst 02_keeping_track.rst 03_periodic_jobs.rst 04_multitasking.rst 05_epochseconds.rst 06_rtc.rst 06_rtc_pcf8583.rst 06_rtc_ds3231.rst 07_shift_register.rst 08_timezones.rst 09_small_improvements.rst 10_prompt_ready.rst 11_persistent_jump_table.rst 11_clocks.rst 11_lastday_of_month.rst 02_keeping_track_2.rst 12_reading_dcf77.rst 20_display_top.rst 21_display_abakus.rst 22_display_7segment_digits.rst 40_main_fairly_minimal.rst 41_main_clock_abakus.rst 42_main_utc_wall_clock.rst 43_main_utc_dcf77_wall_clock.rst Doc_02_unixtime.rst