/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.cc

  • Committer: Tim Marston
  • Date: 2012-03-10 01:25:02 UTC
  • Revision ID: tim@ed.am-20120310012502-v0jwfjghpp63un6n
removed time singleton, not cause it saved much space, but cause i don't want singletons in this project!

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
 
29
29
 * a PC fan is wired up to a 12V power supply
30
30
 
31
 
 * the fan's SENSE (tachometer) pin connected to pin 2 on the
32
 
   Arduino.
 
31
 * the fan's SENSE (tachiometer) pin connected to pin 2 on the
 
32
   arduino.
33
33
 
34
 
 * the pins 4 to 13 on the Arduino should directly drive an LED (the
 
34
 * the pins 4 to 13 on the arduino should directly drive an LED (the
35
35
   LED on pin 4 is in the centre of the clock face and the LED on pin
36
36
   13 is at the outside.
37
37
 
38
38
 * if a longer hand (and a larger clock face) is desired, pin 4 can be
39
39
   used to indirectly drive a transistor which in turn drives several
40
 
   LEDs that turn on and off in unison in the centre of the clock.
 
40
   LEDs that turn on anf off in unison in the centre of the clock.
41
41
 
42
42
 * a button should be attached to pin 3 that grounds it when pressed.
43
43
 
44
 
 * A DS1307 remote clock is connected via I2C on analogue pins 4 and 5.
 
44
 * A DS1307 remote clock is connected via I2C on analog pins 4 and 5.
45
45
 
46
46
Implementation details:
47
47
 
50
50
 * the timing of the drawing of the clock face is recalculated with
51
51
   every rotation of the propeller.
52
52
    
53
 
 * a PC fan actually sends 2 tachometer pulses per revolution, so the
 
53
 * a PC fan actually sends 2 tachiometer pulses per revolution, so the
54
54
   software skips every other one. This means that the clock may
55
55
   appear upside-down if started with the propeller in the wrong
56
 
   position. You will need to experiment to discover the position that
 
56
   position. You will need to experiment to dicsover the position that
57
57
   the propeller must be in when starting the clock.
58
58
    
59
59
Usage instructions:
79
79
#include "button.h"
80
80
#include "time.h"
81
81
#include "Arduino.h"
82
 
#include "modes/analogue_clock.h"
83
 
#include "modes/digital_clock.h"
84
 
#include "modes/test_pattern.h"
85
 
#include "modes/settings_mode.h"
86
 
#include "modes/info_mode.h"
87
 
#include "text.h"
88
 
#include "text_renderer.h"
89
 
#include "common.h"
 
82
#include "analogue_clock.h"
 
83
#include "digital_clock.h"
 
84
#include "test_pattern.h"
90
85
 
91
86
//_____________________________________________________________________________
92
87
//                                                                         data
113
108
static int _major_mode = 0;
114
109
static int _minor_mode = 0;
115
110
 
116
 
#define SETTINGS_MODE_IDX 1
117
111
#define MAIN_MODE_IDX 0
118
112
 
119
113
#define ANALOGUE_CLOCK_IDX 0
120
114
#define DIGITAL_CLOCK_IDX 1
121
 
#define INFO_MODE_IDX 2
122
 
#define TEST_PATTERN_IDX 3
 
115
#define TEST_PATTERN_IDX 2
123
116
 
124
117
//_____________________________________________________________________________
125
118
//                                                                         code
128
121
// activate the current minor mode
129
122
void activate_minor_mode()
130
123
{
131
 
        // reset text
132
 
        Text::reset();
133
 
        leds_off();
134
 
 
135
 
        // give the mode a chance to init
136
124
        switch( _minor_mode ) {
137
 
        case ANALOGUE_CLOCK_IDX: analogue_clock_activate(); break;
138
125
        case DIGITAL_CLOCK_IDX: digital_clock_activate(); break;
139
 
        case INFO_MODE_IDX: info_mode_activate(); break;
140
 
        }
141
 
}
142
 
 
143
 
 
144
 
// activate major mode
145
 
void activate_major_mode()
146
 
{
147
 
        // reset text
148
 
        Text::reset();
149
 
        leds_off();
150
 
 
151
 
        // reset buttons
152
 
        _button.set_press_mode( _major_mode != SETTINGS_MODE_IDX );
153
 
 
154
 
        // give the mode a chance to init
155
 
        switch( _major_mode ) {
156
 
        case MAIN_MODE_IDX: activate_minor_mode(); break;
157
 
        case SETTINGS_MODE_IDX: settings_mode_activate(); break;
158
 
        }
159
 
}
160
 
 
 
126
        }
 
127
}
161
128
 
162
129
// perform button events
163
130
void do_button_events()
174
141
                                switch( _minor_mode ) {
175
142
                                case ANALOGUE_CLOCK_IDX: analogue_clock_press(); break;
176
143
                                case DIGITAL_CLOCK_IDX: digital_clock_press(); break;
177
 
                                case INFO_MODE_IDX: info_mode_press(); break;
178
144
                                }
179
145
                                break;
180
 
                        case SETTINGS_MODE_IDX: settings_mode_press(); break;
181
146
                        }
182
147
                        break;
183
148
 
185
150
                        // long press
186
151
                        switch( _major_mode ) {
187
152
                        case MAIN_MODE_IDX:
188
 
                                if( ++_minor_mode >= 4 )
 
153
                                if( ++_minor_mode >= 3 )
189
154
                                        _minor_mode = 0;
190
 
                                activate_minor_mode();
 
155
                                switch( _minor_mode ) {
 
156
                                case DIGITAL_CLOCK_IDX: digital_clock_activate(); break;
 
157
                                }
191
158
                                break;
192
 
                        case SETTINGS_MODE_IDX: settings_mode_long_press(); break;
193
159
                        }
194
160
                        break;
195
161
 
196
162
                case 3:
197
163
                        // looooong press (change major mode)
198
 
                        if( ++_major_mode > 1 )
 
164
                        if( ++_major_mode > 0 )
199
165
                                _major_mode = 0;
200
 
                        activate_major_mode();
 
166
                        switch( _major_mode ) {
 
167
                        case MAIN_MODE_IDX: _minor_mode = 0; break;
 
168
                        }
 
169
                        activate_minor_mode();
201
170
                        break;
202
171
                }
203
172
        }
216
185
        if( reset ) segment = NUM_SEGMENTS - 1 - CLOCK_SHIFT;
217
186
#endif
218
187
 
219
 
        // reset the text renderer
220
 
        TextRenderer::reset_buffer();
221
 
 
222
 
        // frame reset
223
 
        if( reset ) {
224
 
                switch( _major_mode ) {
225
 
                case MAIN_MODE_IDX:
226
 
                        switch( _minor_mode ) {
227
 
                        case ANALOGUE_CLOCK_IDX: analogue_clock_draw_reset(); break;
228
 
                        case DIGITAL_CLOCK_IDX: digital_clock_draw_reset(); break;
229
 
                        case INFO_MODE_IDX: info_mode_draw_reset(); break;
230
 
                        }
231
 
                        break;
232
 
                case SETTINGS_MODE_IDX: settings_mode_draw_reset(); break;
233
 
                }
234
 
 
235
 
                // tell the text services we're starting a new frame
236
 
                Text::draw_reset();
237
 
        }
238
 
 
239
188
        // draw
240
189
        switch( _major_mode ) {
241
190
        case MAIN_MODE_IDX:
243
192
                case ANALOGUE_CLOCK_IDX: analogue_clock_draw( segment ); break;
244
193
                case DIGITAL_CLOCK_IDX: digital_clock_draw( segment ); break;
245
194
                case TEST_PATTERN_IDX: test_pattern_draw( segment ); break;
246
 
                case INFO_MODE_IDX: info_mode_draw( segment ); break;
247
195
                }
248
196
                break;
249
 
        case SETTINGS_MODE_IDX: settings_mode_draw( segment ); break;
250
197
        }
251
 
        Text::post_draw();
252
 
 
253
 
        // draw any text that was rendered
254
 
        TextRenderer::output_buffer();
255
198
 
256
199
#if CLOCK_FORWARD
257
200
        if( ++segment >= NUM_SEGMENTS ) segment = 0;
305
248
}
306
249
 
307
250
 
308
 
// ISR to handle the pulses from the fan's tachometer
 
251
// ISR to handle the pulses from the fan's tachiometer
309
252
void fan_pulse_handler()
310
253
{
311
254
        // the fan actually sends two pulses per revolution. These pulses
325
268
// main setup
326
269
void setup()
327
270
{
328
 
        // set up an interrupt handler on pin 2 to notice fan pulses
 
271
        // set up an interrupt handler on pin 2 to nitice fan pulses
329
272
        attachInterrupt( 0, fan_pulse_handler, RISING );
330
273
        digitalWrite( 2, HIGH );
331
274
  
339
282
        static int event_times[] = { 5, 500, 4000, 0 };
340
283
        _button.set_event_times( event_times );
341
284
 
342
 
        // initialise RTC
 
285
        // get time from RTC
343
286
        Time::init();
344
287
 
345
 
        // init text renderer
346
 
        TextRenderer::init();
347
 
 
348
288
        // activate the minor mode
349
 
        activate_major_mode();
 
289
        switch( _major_mode ) {
 
290
        case MAIN_MODE_IDX: activate_minor_mode(); break;
 
291
        }
350
292
}
351
293
 
352
294