/elec/propeller-clock

To get this branch, use:
bzr branch http://bzr.ed.am/elec/propeller-clock

« back to all changes in this revision

Viewing changes to src/propeller-clock.ino

  • Committer: edam
  • Date: 2012-02-16 00:08:37 UTC
  • Revision ID: edam@waxworlds.org-20120216000837-ozbyl61w2n2thwa0
update arduino.mk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: c++; compile-command: "BOARD=pro5v make"; -*- */
1
2
/*
2
 
 * propeller-clock.pde
 
3
 * propeller-clock.ino
3
4
 *
4
 
 * Copyright (C) 2011 Tim Marston <edam@waxworlds.org>
 
5
 * Copyright (C) 2011 Tim Marston <tim@ed.am> and Dan Marston.
5
6
 *
6
7
 * This file is part of propeller-clock (hereafter referred to as "this
7
 
 * program"). See http://ed.am/software/arduino/propeller-clock for more
 
8
 * program"). See http://ed.am/dev/software/arduino/propeller-clock for more
8
9
 * information.
9
10
 *
10
11
 * This program is free software: you can redistribute it and/or modify
23
24
 
24
25
/******************************************************************************
25
26
 
26
 
  For a schematic, see propeller-clock.sch.
27
 
 
28
 
  Set up as follows:
29
 
 
30
 
  - a PC fan is wired up to the 12V supply.
31
 
 
32
 
  - the fan's SENSE (tachiometer) pin is connected to pin 2 on the
33
 
    arduino.
34
 
 
35
 
  - the pins 4 to 13 on the arduino should directly drive an LED (the
36
 
    LED on pin 4 is in the centre of the clock face and the LED on pin
37
 
    13 is at the outside.
38
 
 
39
 
  - if a longer hand (and a larger clock face) is desired, pin 4 can
40
 
    be used to indirectly drive (via a MOSFET) multiple LEDs which
41
 
    turn on and off in unison in the centre of the clock.
42
 
 
43
 
  - a button should be attached to pin 3 that grounds it when pressed.
44
 
 
45
 
  Implementation details:
46
 
 
47
 
  - the timing of the drawing of the clock face is recalculated with
48
 
    every rotation of the propeller (for maximum update speed).
49
 
 
50
 
  - pressing the button cycles between display modes
51
 
 
52
 
  - holding down the button for 2 seconds enters "set time" mode. In
53
 
    this mode, the fan must be held still and the LEDs will indicate
54
 
    what number is being entered for each time digit. Pressing the
55
 
    button increments the current digit. Holding it down moves to the
56
 
    next digit (or leaves "set time" mode when there are no more). In
57
 
    order, the digits (with accepted values) are: hours-tens (0 to 2),
58
 
    hours-ones (0 to 9), minutes-tens (0 to 5), minutes-ones (0 to 9).
 
27
Set up:
 
28
 
 
29
 * a PC fan is wired up to a 12V power supply
 
30
 
 
31
 * the fan's SENSE (tachiometer) pin connected to pin 2 on the
 
32
   arduino.
 
33
 
 
34
 * the pins 4 to 13 on the arduino should directly drive an LED (the
 
35
   LED on pin 4 is in the centre of the clock face and the LED on pin
 
36
   13 is at the outside.
 
37
 
 
38
 * if a longer hand (and a larger clock face) is desired, pin 4 can be
 
39
   used to indirectly drive a transistor which in turn drives several
 
40
   LEDs that turn on anf off in unison in the centre of the clock.
 
41
 
 
42
 * a button should be attached to pin 3 that grounds it when pressed.
 
43
 
 
44
 * A DS1307 remote clock is connected via I2C on analog pins 4 and 5.
 
45
 
 
46
Implementation details:
 
47
 
 
48
 * for a schematic, see ../project/propeller-clock.sch.
 
49
 
 
50
 * the timing of the drawing of the clock face is recalculated with
 
51
   every rotation of the propeller.
 
52
    
 
53
 * a PC fan actually sends 2 tachiometer pulses per revolution, so the
 
54
   software skips every other one. This means that the clock may
 
55
   appear upside-down if started with the propeller in the wrong
 
56
   position. You will need to experiment to dicsover the position that
 
57
   the propeller must be in when starting the clock.
 
58
    
 
59
Usage instructions:
 
60
 
 
61
 * pressing the button cycles between variations of the current
 
62
   display mode.
 
63
  
 
64
 * pressing and holding the button for a second cycles between display
 
65
   modes (e.g., analogue and digital).
 
66
 
 
67
 * pressing and holding the button for 5 seconds enters "time set"
 
68
   mode. In this mode, the following applies:
 
69
    - the field that is being set flashes
 
70
    - pressing the button increments the field currently being set
 
71
    - pressing and holding the button for a second cycles through the
 
72
      fields that can be set
 
73
    - pressing and holding the button for 5 seconds sets the time and
 
74
      exits "time set" mode
59
75
 
60
76
******************************************************************************/
61
77
 
62
78
 
63
79
#include <Bounce.h>
 
80
#include <DS1307.h>
 
81
#include <Wire.h>
64
82
 
65
83
//_____________________________________________________________________________
66
84
//                                                                         data
85
103
static bool inc_draw_mode = false;
86
104
 
87
105
// a bounce-managed button
88
 
static Bounce button( 3, 5 );
 
106
static Bounce button( 3, 50 );
89
107
 
90
108
// the time
91
109
static int time_hours = 0;
143
161
}
144
162
 
145
163
 
 
164
// turn an led on/off
 
165
void ledOn( int num, bool on )
 
166
{
 
167
        if( num < 0 || num > 9 ) return;
 
168
 
 
169
        // convert to pin no.
 
170
        num += 4;
 
171
 
 
172
        // pin 4 needs to be inverted (it's driving a PNP)
 
173
        // NOTE: PIN 4 TEMPORARILY DISABLED
 
174
        if( num == 4 ) on = true; //!on
 
175
 
 
176
        digitalWrite( num, on? HIGH : LOW );
 
177
}
 
178
 
 
179
 
146
180
// draw a segment for the test display
147
181
void drawNextSegment_test( bool reset )
148
182
{
152
186
        segment++;
153
187
 
154
188
        // turn on inside and outside LEDs
155
 
        digitalWrite( 4, HIGH );
156
 
        digitalWrite( 13, HIGH );
 
189
        ledOn( 0, true );
 
190
        ledOn( 9, true );
157
191
 
158
192
        // display segment number in binary across in the inside LEDs,
159
193
        // with the LED on pin 12 showing the least-significant bit
160
194
        for( int a = 0; a < 8; a++ )
161
 
                digitalWrite( 12 - a, ( ( segment >> a ) & 1 )? HIGH : LOW );
 
195
                ledOn( 8 - a, ( segment >> a ) & 1 );
162
196
}
163
197
 
164
198
 
165
199
// draw a segment for the time display
166
200
void drawNextSegment_time( bool reset )
167
201
{
168
 
        static unsigned int second = 0;
169
 
        static unsigned int segment = 0;
 
202
        static int second = 0;
 
203
        static int segment = 0;
170
204
 
171
205
        // handle display reset
172
206
        if( reset ) {
175
209
        }
176
210
 
177
211
        // what needs to be drawn?
178
 
        bool draw_tick = second % 5 == 0;
179
 
        bool draw_second = second == time_seconds;
180
 
        bool draw_minute = second == time_minute;
181
 
        bool draw_hour = second == time_hour;
 
212
        bool draw_tick = !segment && second % 5 == 0;
 
213
        bool draw_second = !segment && second == time_seconds;
 
214
        bool draw_minute = !segment && second == time_minutes;
 
215
        bool draw_hour = !segment && second == time_hours;
182
216
 
183
217
        // set the LEDs
184
 
        digitalWrite( 13, HIGH );
185
 
        digitalWrite( 12, draw_tick || draw_minute );
186
 
        for( int a = 10; a <= 11; a++ )
187
 
                digitalWrite( a, draw_minute || draw_second );
188
 
        for( int a = 4; a <= 9; a++ )
189
 
                digitalWrite( 10, draw_minute | draw_second || draw_hour );
 
218
        ledOn( 9, true );
 
219
        ledOn( 8, draw_tick || draw_minute );
 
220
        for( int a = 6; a <= 7; a++ )
 
221
                ledOn( a, draw_minute || draw_second );
 
222
        for( int a = 0; a <= 5; a++ )
 
223
                ledOn( a, draw_minute || draw_second || draw_hour );
190
224
 
191
225
        // inc position
192
226
        if( ++segment >= NUM_SECOND_SEGMENTS ) {
291
325
 
292
326
        // set up mode-switch button on pin 3
293
327
        pinMode( 3, INPUT );
 
328
        digitalWrite( 3, HIGH );
 
329
 
 
330
        // get the time from the real-time clock
 
331
        int rtc_data[ 7 ];
 
332
        RTC.get( rtc_data, true );
 
333
        time_hours = rtc_data[ DS1307_HR ];
 
334
        time_minutes = rtc_data[ DS1307_MIN ];
 
335
        time_seconds = rtc_data[ DS1307_SEC ];
294
336
 
295
337
        // serial comms
296
338
        Serial.begin( 9600 );