/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: 2013-03-31 17:07:11 UTC
  • Revision ID: tim@ed.am-20130331170711-okfhn3wx9y0eo99a
updated the schematic to increase minimum font size

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: c++; compile-command: "BOARD=pro5v make"; -*- */
 
1
/* -*- mode: c++; compile-command: "make"; -*- */
2
2
/*
3
3
 * propeller-clock.ino
4
4
 *
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"
 
82
#include "modes/switcher_major_mode.h"
 
83
#include "modes/settings_major_mode.h"
 
84
#include "modes/analogue_clock_mode.h"
 
85
#include "modes/digital_clock_mode.h"
 
86
#include "modes/info_mode.h"
 
87
#include "modes/test_pattern_mode.h"
86
88
#include "text.h"
87
89
#include "text_renderer.h"
88
90
#include "common.h"
108
110
// the button
109
111
static Button _button( 3 );
110
112
 
111
 
// modes
112
 
static int _major_mode = 0;
113
 
static int _minor_mode = 0;
114
 
 
115
 
#define MAIN_MODE_IDX 1
116
 
#define SETTINGS_MODE_IDX 0
117
 
 
118
 
#define ANALOGUE_CLOCK_IDX 0
119
 
#define DIGITAL_CLOCK_IDX 1
120
 
#define TEST_PATTERN_IDX 2
 
113
// major modes
 
114
static MajorMode *_modes[ 3 ];
 
115
 
 
116
// current major mode
 
117
static int _mode = 0;
 
118
 
 
119
// interupt handler's "ignore every other" flag
 
120
static bool _pulse_ignore = true;
121
121
 
122
122
//_____________________________________________________________________________
123
123
//                                                                         code
124
124
 
125
 
 
126
 
// activate the current minor mode
127
 
void activate_minor_mode()
128
 
{
129
 
        // reset text
130
 
        Text::reset();
131
 
        leds_off();
132
 
 
133
 
        // give the mode a chance to init
134
 
        switch( _minor_mode ) {
135
 
        case ANALOGUE_CLOCK_IDX: analogue_clock_activate(); break;
136
 
        case DIGITAL_CLOCK_IDX: digital_clock_activate(); break;
137
 
        }
138
 
}
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
 
 
159
125
// perform button events
160
126
void do_button_events()
161
127
{
166
132
                {
167
133
                case 1:
168
134
                        // short press
169
 
                        switch( _major_mode ) {
170
 
                        case MAIN_MODE_IDX:
171
 
                                switch( _minor_mode ) {
172
 
                                case ANALOGUE_CLOCK_IDX: analogue_clock_press(); break;
173
 
                                case DIGITAL_CLOCK_IDX: digital_clock_press(); break;
174
 
                                }
175
 
                                break;
176
 
                        case SETTINGS_MODE_IDX: settings_mode_press(); break;
177
 
                        }
 
135
                        _modes[ _mode ]->press();
178
136
                        break;
179
 
 
180
137
                case 2:
181
138
                        // long press
182
 
                        switch( _major_mode ) {
183
 
                        case MAIN_MODE_IDX:
184
 
                                if( ++_minor_mode >= 3 )
185
 
                                        _minor_mode = 0;
186
 
                                activate_minor_mode();
187
 
                                break;
188
 
                        case SETTINGS_MODE_IDX: settings_mode_long_press(); break;
189
 
                        }
 
139
                        _modes[ _mode ]->long_press();
190
140
                        break;
191
 
 
192
141
                case 3:
193
142
                        // looooong press (change major mode)
194
 
                        if( ++_major_mode > 1 )
195
 
                                _major_mode = 0;
196
 
                        activate_major_mode();
 
143
                        _modes[ _mode ]->deactivate();
 
144
                        if( !_modes[ ++_mode ] ) _mode = 0;
 
145
                        _modes[ _mode ]->activate();
 
146
                        break;
 
147
                case 4:
 
148
                        // switch display upside-down
 
149
                        _pulse_ignore = !_pulse_ignore;
197
150
                        break;
198
151
                }
199
152
        }
204
157
void draw_next_segment( bool reset )
205
158
{
206
159
        // keep track of segment
 
160
        static int segment = 0;
207
161
#if CLOCK_FORWARD
208
 
        static int segment = ( NUM_SEGMENTS - CLOCK_SHIFT ) % NUM_SEGMENTS;
209
162
        if( reset ) segment = ( NUM_SEGMENTS - CLOCK_SHIFT ) % NUM_SEGMENTS;
210
163
#else
211
 
        static int segment = NUM_SEGMENTS - 1 - CLOCK_SHIFT;
212
164
        if( reset ) segment = NUM_SEGMENTS - 1 - CLOCK_SHIFT;
213
165
#endif
214
166
 
215
 
        // reset the text renderer
 
167
        // reset the text renderer's buffer
216
168
        TextRenderer::reset_buffer();
217
169
 
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
 
                }
 
170
        if( reset )
 
171
        {
 
172
                _modes[ _mode ]->draw_reset();
229
173
 
230
174
                // tell the text services we're starting a new frame
231
175
                Text::draw_reset();
232
176
        }
233
177
 
234
178
        // draw
235
 
        switch( _major_mode ) {
236
 
        case MAIN_MODE_IDX:
237
 
                switch( _minor_mode ) {
238
 
                case ANALOGUE_CLOCK_IDX: analogue_clock_draw( segment ); break;
239
 
                case DIGITAL_CLOCK_IDX: digital_clock_draw( segment ); break;
240
 
                case TEST_PATTERN_IDX: test_pattern_draw( segment ); break;
241
 
                }
242
 
                break;
243
 
        case SETTINGS_MODE_IDX: settings_mode_draw( segment ); break;
244
 
        }
245
 
 
246
 
        // draw any text that was rendered
 
179
        _modes[ _mode ]->draw( segment );
 
180
 
 
181
        // draw text
 
182
        Text::draw( segment );
 
183
 
 
184
        // draw text rednerer's buffer
247
185
        TextRenderer::output_buffer();
248
186
 
249
187
#if CLOCK_FORWARD
298
236
}
299
237
 
300
238
 
301
 
// ISR to handle the pulses from the fan's tachiometer
 
239
// ISR to handle the pulses from the fan's tachometer
302
240
void fan_pulse_handler()
303
241
{
304
242
        // the fan actually sends two pulses per revolution. These pulses
305
243
        // may not be exactly evenly distributed around the rotation, so
306
244
        // we can't recalculate times on every pulse. Instead, we ignore
307
245
        // every other pulse so timings are based on a complete rotation.
308
 
        static bool ignore = true;
309
 
        ignore = !ignore;
310
 
        if( !ignore )
 
246
        _pulse_ignore = !_pulse_ignore;
 
247
        if( !_pulse_ignore )
311
248
        {
312
249
                // set a new pulse time
313
250
                _new_pulse_at = micros();
318
255
// main setup
319
256
void setup()
320
257
{
321
 
        // set up an interrupt handler on pin 2 to nitice fan pulses
 
258
        // set up an interrupt handler on pin 2 to notice fan pulses
322
259
        attachInterrupt( 0, fan_pulse_handler, RISING );
323
260
        digitalWrite( 2, HIGH );
324
261
  
329
266
        // set up mode-switch button on pin 3
330
267
        pinMode( 3, INPUT );
331
268
        digitalWrite( 3, HIGH );
332
 
        static int event_times[] = { 5, 500, 4000, 0 };
 
269
        static int event_times[] = { 10, 500, 2000, 4000, 0 };
333
270
        _button.set_event_times( event_times );
334
271
 
335
272
        // initialise RTC
336
 
        Time::init();
 
273
        Time::load_time();
337
274
 
338
275
        // init text renderer
339
276
        TextRenderer::init();
340
277
 
341
 
        // activate the minor mode
342
 
        activate_major_mode();
 
278
        // reset text
 
279
        Text::reset();
 
280
        leds_off();
 
281
 
 
282
        static SwitcherMajorMode switcher;
 
283
        static SettingsMajorMode settings( _button );
 
284
 
 
285
        // add major modes
 
286
        int mode = 0;
 
287
        _modes[ mode++ ] = &switcher;
 
288
        _modes[ mode++ ] = &settings;
 
289
        _modes[ mode ] = 0;
 
290
 
 
291
        // activate the current major mode
 
292
        _modes[ _mode ]->activate();
343
293
}
344
294
 
345
295