/*
 * $Id: README,v 1.1 2008/05/11 08:50:37 fvecoven Exp $
 *
 * Copyright (C) 2008 Frederic Vecoven
 *
 * This file is part of NixieClock
 *
 * NixieClock is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * NixieClock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

Welcome.

This is the README file of NixieClock, a nixie clock featuring :

- control of 6 nixie tubes
- automatic brightness control
- dcf 77 synchronization
- infra-red remote control
- alarm
- many software features, such as 
  - fade in/out digits
  - alarm on/off
  - date
  - tube saving (can be turned off/on automatically)
  - cathode poisoning prevention
  - tube "on time" counter
  - powerful editor (time, date, settings, ...)

Many nixie clocks have been designed, and for most of them, the
hardware schematics are available on the web. However, I haven't seen
many software being released as open-source. Hopefully, this one will
fill the gap. Feel free to use it, to modify it, to enhance it, etc...

The software is written in C, using the microchip MCC18 compiler. C allows
faster development times, and more readability of the code (well, sometimes!).
Anyway, it is pretty easy to rewrite this in assembly if required.


This document explains briefly the hardware design, which has nothing
particular. Then the software is also briefly explained. With this
introduction, reading the code should be straightforward.



Hardware design
===============

Tubes
-----

The design is a classic multiplex, where we have 2 tubes lit at
the same time, and there are 6 tubes. Therefore, we have

- 3 anodes to control  (ANODE0, ANODE1 and ANODE2, see NixieClock.h)
- 2x 4 bits going to the BCD decoder (PORTB)
- 2x 1 bit to control the decimal dots (DP1 and DP2, see NixieClock.h)

Tinme keeping
-------------
A Dallas (Maxim) DS1307 chip is used to keep the time.



DCF77
-----

The output of the DCF77 receiver is fed into one pin of the microcontroller.
It's defined as DCF_PIN in NixieClock.h. There are also two LEDs that can
be used to show the signal, one red and one green. The signal is shown on
one LED : the green one if we are synced with DCF, the red one otherwise.

On my board, the antenna is on the PCB, and the switching power supply
was preventing correct reception of DCF. Therefore, the tubes and the
power supply can be switched off completely, allowing proper DCF77
reception. The pin that controls the high voltage generator is defined
as HV_PIN. 

Note that the 2 LEDs and the decimal dots of the tubes are controlled
by the same 2 pins of the microcontroller. The polarity is reversed
for the LED. (To light a LED, set the output pin to '0'. To set a decimal
dot, set the output pin to '1').


IR reception
------------

The user interacts with the clock using a remote control. An IR
receiver is used to receive the signal, and this signal is fed in
the microcontroller on pin IR_SIGNAL. Note that the code requires
a pin which generates an interrupt when an edge is detected.


ALARM
-----

The clock can generate beeps and/or alarms. An output pin is
toggled when needed, and it's defined as ALARM_PIN.


Brightness control
------------------

An LDR is connected to an analog input pin, and the A/D of the pic
is used to read the voltage. The code uses LDR_PIN to refer to it.



Software design
===============

The software is based on 3 interrupts :
- timer0        (tube refresh, dcf77)
- timer1	(time)
- external pin	(IR)

Timer0
------

Timer0 overflows every 100us. Its main role is to refresh the tubes,
but it also provides a time base for the IR decoding routine, and
also for DCF reception.

To allow various brightness and digits fade in/out, each tube receives
33 x 100uS time. The 33rd period is blanking, to avoid ghosting. During
this period, all tubes are turned off. So, we have ~3.3ms per tube
and we have 3 pairs to refresh, which gives ~100Hz refresh.

During the first 32 periods, we either show nothing (depending on the
brightness setting) or a digit, or its successor (for fading). 

Since timer0 overflows very often (100us, at 32MHz, with 4 cycles per
instruction, is about 800 instructions), we should keep it as simple
as possible. The work to encode values to BCD, to compute the threshold
for fading, etc.. is all done outside timer0 interrupt routine.


Timer1
------

Timer1 is incrementing when an edge is detected on its external pin. 
This pin is connected to the DS1307 chip, which provides a clock running
at 4096Hz. We program it so that it overflows 256 times per second, 
giving us a nice tick counter.

Timer1 interrupt routine takes care of :
- increment the time
- generate a beep or alarm
- compute the fading threshold


External pin
------------

The IR receiver is connected to a pin which generates an interrupt
when an edge is crossed. The interrupt handler is a finite state machine
which handles the IR protocol. To measure the duration of various pulses,
we change the polarity of the edge trigger, and reset a counter. At
the next interrupt, a pulse has just ended, and the counter holds the
pulse length in 100us increments (since this counter is incremented by
timer0).

I happen to have bought really nice tiny remote control at Weird Stuff
(at $1 each !). These remote controls use the NEC protocol, which is
what this routine decodes. I also wrote a RC5 decoder using a similar
scheme.


Main loop
---------

Each interrupt handler can set flags when certain actions are
required :

- a minute has elapsed
- an hour has elapsed
- a key has been pressed on the remote control
- we should sample the ambiant luminosity to adjust brightness
- ...

The main loops does nothing but checks these flags. If a flag
is set, the appropriate handler is called, and the flag is reset.


The clock can be in various modes :

- MODE_OFF : the user has pressed the power key. The clock will remain
             in this mode until the power key is pressed again.

- MODE_AUTO_OFF : the clock has turned itself off automatically. It will 
                  stay in this mode until the user powers it on, or until 
                  it's time to turn on automatically.

- MODE_TIME : the main mode, where time is shown. See routine time_refresh()
              in time.c

- MODE_DCF : the user has manually put the clock in DCF mode. 

- MODE_AUTO_DCF : the clock has turned itself off automatically, and has
                  entered DCF mode. It will remain in this mode until a 
		  DCF frame is received properly (in which case the set_time()
		  routine is called) or until it's time to be turned on.

- MODE_PREVENT : cathode poisoning prevention. The clock will turn off the
    	       	 100Hz refresh, and will show a pair of digits at a time,
		 during a user defined period. 

- MODE_EDITOR : the clock is in editor mode, where various parameters can 
  	      	be shown and/or edited. See editor.c for details.
		

The editor is very versatile, and is configured with an array of menu_t
structures. The editor prevents the user from entering invalid values,
but also automatically correct digit at the right of the cursor. 

For example, suppose the we are editing a TYPE_4_TIME value, which is
just HH:MM. Also suppose that the current setting is 18:35. When
we enter the editor, digit '1' will blink. If you press '2', that would
make 28:35 which is invalid, so the editor will automatically change '8'
to '0' for you. The current value will then be 20:35, and '0' will blink.
A similar scheme is used for dates, where things are a little more 
complicated, since we handle leap-years, etc...  Try it, you'll love it.

The main reason to implement this is to allow the user to set anything
without having to scroll back to the left in order to change a digit.

The routines which check and correct values are time4_valid(), time6_valid(),
int_valid() and date_valid(). 

The main buttons for the editor are :
- ENTER : start editing or accept the current setting (a double-beep confirms)
- CH_UP & CH_DOWN : go to the next/previous setting
- VOL_UP & VOL_DOWN : while editing a digit, increment or decrement it.
- KEY0 .. KEY9 : direct entry of a digit

Any invalid key will trigger a single short beep.


Future work
===========

This work is release 1.x. This software is supposed to evolve, based
on received feedback and/or modifications by other developers or
clock enthusiams. 

Ideas and suggestions are always welcome. Please send them to

frederic AT vecoven.com


Enjoy :)

