/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-05-17 22:49:36 UTC
  • Revision ID: tim@ed.am-20120517224936-0wgyem932dlq5bs4
various tweaks, a (failed) attempt to fix text reset bug and added TODO

Show diffs side-by-side

added added

removed removed

1
 
/* -*- mode: c++; compile-command: "make"; -*- */
 
1
/* -*- mode: c++; compile-command: "BOARD=pro5v 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/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"
 
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
86
#include "modes/info_mode.h"
87
 
#include "modes/test_pattern_mode.h"
88
87
#include "text.h"
89
88
#include "text_renderer.h"
90
89
#include "common.h"
110
109
// the button
111
110
static Button _button( 3 );
112
111
 
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;
 
112
// modes
 
113
static int _major_mode = 0;
 
114
static int _minor_mode = 0;
 
115
 
 
116
#define SETTINGS_MODE_IDX 1
 
117
#define MAIN_MODE_IDX 0
 
118
 
 
119
#define ANALOGUE_CLOCK_IDX 0
 
120
#define DIGITAL_CLOCK_IDX 1
 
121
#define INFO_MODE_IDX 2
 
122
#define TEST_PATTERN_IDX 3
121
123
 
122
124
//_____________________________________________________________________________
123
125
//                                                                         code
124
126
 
 
127
 
 
128
// activate the current minor mode
 
129
void activate_minor_mode()
 
130
{
 
131
        // reset text
 
132
        Text::reset();
 
133
        leds_off();
 
134
 
 
135
        // give the mode a chance to init
 
136
        switch( _minor_mode ) {
 
137
        case ANALOGUE_CLOCK_IDX: analogue_clock_activate(); break;
 
138
        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
 
 
161
 
125
162
// perform button events
126
163
void do_button_events()
127
164
{
132
169
                {
133
170
                case 1:
134
171
                        // short press
135
 
                        _modes[ _mode ]->press();
 
172
                        switch( _major_mode ) {
 
173
                        case MAIN_MODE_IDX:
 
174
                                switch( _minor_mode ) {
 
175
                                case ANALOGUE_CLOCK_IDX: analogue_clock_press(); break;
 
176
                                case DIGITAL_CLOCK_IDX: digital_clock_press(); break;
 
177
                                case INFO_MODE_IDX: info_mode_press(); break;
 
178
                                }
 
179
                                break;
 
180
                        case SETTINGS_MODE_IDX: settings_mode_press(); break;
 
181
                        }
136
182
                        break;
 
183
 
137
184
                case 2:
138
185
                        // long press
139
 
                        _modes[ _mode ]->long_press();
 
186
                        switch( _major_mode ) {
 
187
                        case MAIN_MODE_IDX:
 
188
                                if( ++_minor_mode >= 4 )
 
189
                                        _minor_mode = 0;
 
190
                                activate_minor_mode();
 
191
                                break;
 
192
                        case SETTINGS_MODE_IDX: settings_mode_long_press(); break;
 
193
                        }
140
194
                        break;
 
195
 
141
196
                case 3:
142
197
                        // looooong press (change 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;
 
198
                        if( ++_major_mode > 1 )
 
199
                                _major_mode = 0;
 
200
                        activate_major_mode();
150
201
                        break;
151
202
                }
152
203
        }
157
208
void draw_next_segment( bool reset )
158
209
{
159
210
        // keep track of segment
160
 
        static int segment = 0;
161
211
#if CLOCK_FORWARD
 
212
        static int segment = ( NUM_SEGMENTS - CLOCK_SHIFT ) % NUM_SEGMENTS;
162
213
        if( reset ) segment = ( NUM_SEGMENTS - CLOCK_SHIFT ) % NUM_SEGMENTS;
163
214
#else
 
215
        static int segment = NUM_SEGMENTS - 1 - CLOCK_SHIFT;
164
216
        if( reset ) segment = NUM_SEGMENTS - 1 - CLOCK_SHIFT;
165
217
#endif
166
218
 
167
 
        // reset the text renderer's buffer
 
219
        // reset the text renderer
168
220
        TextRenderer::reset_buffer();
169
221
 
170
 
        if( reset )
171
 
        {
172
 
                _modes[ _mode ]->draw_reset();
 
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
                }
173
234
 
174
235
                // tell the text services we're starting a new frame
175
236
                Text::draw_reset();
176
237
        }
177
238
 
178
239
        // draw
179
 
        _modes[ _mode ]->draw( segment );
180
 
 
181
 
        // draw text
182
 
        Text::draw( segment );
183
 
 
184
 
        // draw text rednerer's buffer
 
240
        switch( _major_mode ) {
 
241
        case MAIN_MODE_IDX:
 
242
                switch( _minor_mode ) {
 
243
                case ANALOGUE_CLOCK_IDX: analogue_clock_draw( segment ); break;
 
244
                case DIGITAL_CLOCK_IDX: digital_clock_draw( segment ); break;
 
245
                case TEST_PATTERN_IDX: test_pattern_draw( segment ); break;
 
246
                case INFO_MODE_IDX: info_mode_draw( segment ); break;
 
247
                }
 
248
                break;
 
249
        case SETTINGS_MODE_IDX: settings_mode_draw( segment ); break;
 
250
        }
 
251
        Text::post_draw();
 
252
 
 
253
        // draw any text that was rendered
185
254
        TextRenderer::output_buffer();
186
255
 
187
256
#if CLOCK_FORWARD
243
312
        // may not be exactly evenly distributed around the rotation, so
244
313
        // we can't recalculate times on every pulse. Instead, we ignore
245
314
        // every other pulse so timings are based on a complete rotation.
246
 
        _pulse_ignore = !_pulse_ignore;
247
 
        if( !_pulse_ignore )
 
315
        static bool ignore = true;
 
316
        ignore = !ignore;
 
317
        if( !ignore )
248
318
        {
249
319
                // set a new pulse time
250
320
                _new_pulse_at = micros();
266
336
        // set up mode-switch button on pin 3
267
337
        pinMode( 3, INPUT );
268
338
        digitalWrite( 3, HIGH );
269
 
        static int event_times[] = { 10, 500, 2000, 4000, 0 };
 
339
        static int event_times[] = { 5, 500, 4000, 0 };
270
340
        _button.set_event_times( event_times );
271
341
 
272
342
        // initialise RTC
273
 
        Time::load_time();
 
343
        Time::init();
274
344
 
275
345
        // init text renderer
276
346
        TextRenderer::init();
277
347
 
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();
 
348
        // activate the minor mode
 
349
        activate_major_mode();
293
350
}
294
351
 
295
352