/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: edam
  • Date: 2012-03-23 15:56:07 UTC
  • Revision ID: tim@ed.am-20120323155607-6h8pc0c6o35nl179
switch button to no interim presses during settings mode; added NVRAM support

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 (tachiometer) pin connected to pin 2 on the
32
 
   arduino.
 
31
 * the fan's SENSE (tachometer) 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 anf off in unison in the centre of the clock.
 
40
   LEDs that turn on and 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 analog pins 4 and 5.
 
44
 * A DS1307 remote clock is connected via I2C on analogue 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 tachiometer pulses per revolution, so the
 
53
 * a PC fan actually sends 2 tachometer 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 dicsover the position that
 
56
   position. You will need to experiment to discover the position that
57
57
   the propeller must be in when starting the clock.
58
58
    
59
59
Usage instructions:
82
82
#include "analogue_clock.h"
83
83
#include "digital_clock.h"
84
84
#include "test_pattern.h"
 
85
#include "settings_mode.h"
 
86
#include "text.h"
 
87
#include "text_renderer.h"
 
88
#include "common.h"
85
89
 
86
90
//_____________________________________________________________________________
87
91
//                                                                         data
108
112
static int _major_mode = 0;
109
113
static int _minor_mode = 0;
110
114
 
111
 
#define MAIN_MODE_IDX 0
 
115
#define MAIN_MODE_IDX 1
 
116
#define SETTINGS_MODE_IDX 0
112
117
 
113
118
#define ANALOGUE_CLOCK_IDX 0
114
119
#define DIGITAL_CLOCK_IDX 1
121
126
// activate the current minor mode
122
127
void activate_minor_mode()
123
128
{
 
129
        // reset text
 
130
        Text::reset();
 
131
        leds_off();
 
132
 
 
133
        // give the mode a chance to init
124
134
        switch( _minor_mode ) {
 
135
        case ANALOGUE_CLOCK_IDX: analogue_clock_activate(); break;
125
136
        case DIGITAL_CLOCK_IDX: digital_clock_activate(); break;
126
137
        }
127
138
}
128
139
 
 
140
 
 
141
// activate major mode
 
142
void activate_major_mode()
 
143
{
 
144
        // reset text
 
145
        Text::reset();
 
146
        leds_off();
 
147
 
 
148
        // reset buttons
 
149
        _button.set_press_mode( _major_mode != SETTINGS_MODE_IDX );
 
150
 
 
151
        // give the mode a chance to init
 
152
        switch( _major_mode ) {
 
153
        case MAIN_MODE_IDX: activate_minor_mode(); break;
 
154
        case SETTINGS_MODE_IDX: settings_mode_activate(); break;
 
155
        }
 
156
}
 
157
 
 
158
 
129
159
// perform button events
130
160
void do_button_events()
131
161
{
143
173
                                case DIGITAL_CLOCK_IDX: digital_clock_press(); break;
144
174
                                }
145
175
                                break;
 
176
                        case SETTINGS_MODE_IDX: settings_mode_press(); break;
146
177
                        }
147
178
                        break;
148
179
 
152
183
                        case MAIN_MODE_IDX:
153
184
                                if( ++_minor_mode >= 3 )
154
185
                                        _minor_mode = 0;
155
 
                                switch( _minor_mode ) {
156
 
                                case DIGITAL_CLOCK_IDX: digital_clock_activate(); break;
157
 
                                }
 
186
                                activate_minor_mode();
158
187
                                break;
 
188
                        case SETTINGS_MODE_IDX: settings_mode_long_press(); break;
159
189
                        }
160
190
                        break;
161
191
 
162
192
                case 3:
163
193
                        // looooong press (change major mode)
164
 
                        if( ++_major_mode > 0 )
 
194
                        if( ++_major_mode > 1 )
165
195
                                _major_mode = 0;
166
 
                        switch( _major_mode ) {
167
 
                        case MAIN_MODE_IDX: _minor_mode = 0; break;
168
 
                        }
169
 
                        activate_minor_mode();
 
196
                        activate_major_mode();
170
197
                        break;
171
198
                }
172
199
        }
185
212
        if( reset ) segment = NUM_SEGMENTS - 1 - CLOCK_SHIFT;
186
213
#endif
187
214
 
 
215
        // reset the text renderer
 
216
        TextRenderer::reset_buffer();
 
217
 
 
218
        // frame reset
 
219
        if( reset ) {
 
220
                switch( _major_mode ) {
 
221
                case MAIN_MODE_IDX:
 
222
                        switch( _minor_mode ) {
 
223
                        case ANALOGUE_CLOCK_IDX: analogue_clock_draw_reset(); break;
 
224
                        case DIGITAL_CLOCK_IDX: digital_clock_draw_reset(); break;
 
225
                        }
 
226
                        break;
 
227
                case SETTINGS_MODE_IDX: settings_mode_draw_reset(); break;
 
228
                }
 
229
 
 
230
                // tell the text services we're starting a new frame
 
231
                Text::draw_reset();
 
232
        }
 
233
 
188
234
        // draw
189
235
        switch( _major_mode ) {
190
236
        case MAIN_MODE_IDX:
194
240
                case TEST_PATTERN_IDX: test_pattern_draw( segment ); break;
195
241
                }
196
242
                break;
 
243
        case SETTINGS_MODE_IDX: settings_mode_draw( segment ); break;
197
244
        }
198
245
 
 
246
        // draw any text that was rendered
 
247
        TextRenderer::output_buffer();
 
248
 
199
249
#if CLOCK_FORWARD
200
250
        if( ++segment >= NUM_SEGMENTS ) segment = 0;
201
251
#else
282
332
        static int event_times[] = { 5, 500, 4000, 0 };
283
333
        _button.set_event_times( event_times );
284
334
 
 
335
        // initialise RTC
 
336
        Time::init();
 
337
 
 
338
        // init text renderer
 
339
        TextRenderer::init();
 
340
 
285
341
        // activate the minor mode
286
 
        switch( _major_mode ) {
287
 
        case MAIN_MODE_IDX: activate_minor_mode(); break;
288
 
        }
 
342
        activate_major_mode();
289
343
}
290
344
 
291
345
 
306
360
                calculate_segment_times();
307
361
 
308
362
                // keep track of time
309
 
                Time &time = Time::get_instance();
310
 
                time.update();
 
363
                Time::update();
311
364
 
312
365
                // perform button events
313
366
                do_button_events();