/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 propeller-clock/propeller-clock.pde

  • Committer: edam
  • Date: 2011-11-04 15:07:26 UTC
  • Revision ID: edam@waxworlds.org-20111104150726-0evv5cetrckzg9do
cleaned-up info

Show diffs side-by-side

added added

removed removed

1
 
/*
2
 
 * propeller-clock.pde
3
 
 *
4
 
 * Copyright (C) 2011 Tim Marston <edam@waxworlds.org>
5
 
 *
6
 
 * 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
 
 * information.
9
 
 *
10
 
 * This program is free software: you can redistribute it and/or modify
11
 
 * it under the terms of the GNU Lesser General Public License as published
12
 
 * by the Free Software Foundation, either version 3 of the License, or
13
 
 * (at your option) any later version.
14
 
 *
15
 
 * This program is distributed in the hope that it will be useful,
16
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 
 * GNU Lesser General Public License for more details.
19
 
 *
20
 
 * You should have received a copy of the GNU Lesser General Public License
21
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 
 */
23
 
 
24
 
//_____________________________________________________________________________
25
 
//                                                                         data
26
 
 
27
 
 
28
 
// when non-zero, the time (in microseconds) of a new fan pulse that
29
 
// has just occurred, which means that segment drawing needs to be
30
 
// restarted
31
 
static unsigned long new_pulse_at = 0;
32
 
 
33
 
// the time (in microseconds) when the last fan pulse occurred
34
 
static unsigned long last_pulse_at = 0;
35
 
 
36
 
// duration (in microseconds) that a segment should be displayed
37
 
static unsigned long segment_step = 0;
38
 
 
39
 
// remainder after divisor and a tally of the remainders for each segment
40
 
static unsigned long segment_step_sub_step = 0;
41
 
static unsigned long segment_step_sub = 0;
42
 
 
43
 
// display mode
44
 
static
45
 
 
46
 
 
47
 
//_____________________________________________________________________________
48
 
//                                                                         code
49
 
 
50
 
 
51
 
// ISR to handle the pulses from the fan's tachiometer
52
 
void fanPulseHandler()
53
 
{
54
 
        // the fan actually sends two pulses per revolution. These pulses
55
 
        // may not be exactly evenly distributed around the rotation, so
56
 
        // we can't recalculate times on every pulse. Instead, we ignore
57
 
        // every other pulse so timings are based on a complete rotation.
58
 
        static bool ignore = true;
59
 
        ignore = !ignore;
60
 
        if( !ignore )
61
 
        {
62
 
                // set a new pulse time
63
 
                new_pulse_at = micros();
64
 
        }
65
 
}
66
 
 
67
 
 
68
 
// draw a particular segment
69
 
void drawNextSegment( bool reset )
70
 
{
71
 
        static unsigned int segment = 0;
72
 
        if( reset ) segment = 0;
73
 
        segment++;
74
 
 
75
 
        for( int a = 0; a < 10; a++ )
76
 
                digitalWrite( a + 4, ( ( segment >> a ) & 1 )? HIGH : LOW );
77
 
}
78
 
 
79
 
 
80
 
// calculate time constants when a new pulse has occurred
81
 
void calculateSegmentTimes()
82
 
{
83
 
        // check for overflows, and only recalculate times if there isn't
84
 
        // one (if there is, we'll just go with the last pulse's times)
85
 
        if( new_pulse_at > last_pulse_at )
86
 
        {
87
 
                // new segment stepping times
88
 
                unsigned long delta = new_pulse_at - last_pulse_at;
89
 
                segment_step = delta / NUM_SEGMENTS;
90
 
                segment_step_sub = 0;
91
 
                segment_step_sub_step = delta % NUM_SEGMENTS;
92
 
        }
93
 
 
94
 
        // now we have dealt with this pulse, save the pulse time and
95
 
        // clear new_pulse_at, ready for the next pulse
96
 
        last_pulse_at = new_pulse_at;
97
 
        new_pulse_at = 0;
98
 
}
99
 
 
100
 
 
101
 
// wait until it is time to draw the next segment or a new pulse has
102
 
// occurred
103
 
void waitTillNextSegment( bool reset )
104
 
{
105
 
        static unsigned long end_time = 0;
106
 
 
107
 
        // handle reset
108
 
        if( reset )
109
 
                end_time = last_pulse_at;
110
 
 
111
 
        // work out the time that this segment should be displayed until
112
 
        end_time += segment_step;
113
 
        semgment_step_sub += semgment_step_sub_step;
114
 
        if( semgment_step_sub >= NUM_SEGMENTS ) {
115
 
                semgment_step_sub -= NUM_SEGMENTS;
116
 
                end_time++;
117
 
        }
118
 
 
119
 
        // wait
120
 
        while( micros() < end_time && !new_pulse_at );
121
 
}
122
 
 
123
 
 
124
 
// main setup
125
 
void setup()
126
 
{
127
 
        // set up an interrupt handler on pin 2 to nitice fan pulses
128
 
        attachInterrupt( 0, fanPulseHandler, RISING );
129
 
        digitalWrite( 2, HIGH );
130
 
  
131
 
        // set up output pins (4 to 13) for the led array
132
 
        for( int a = 4; a < 14; a++ )
133
 
                pinMode( a, OUTPUT );
134
 
 
135
 
        // serial comms
136
 
        Serial.begin( 9600 );
137
 
}
138
 
 
139
 
 
140
 
// main loop
141
 
void loop()
142
 
{
143
 
        // if there has been a new pulse, we'll be resetting the display
144
 
        bool reset = new_pulse_at? true : false;
145
 
 
146
 
        // draw this segment
147
 
        drawNextSegment( reset );
148
 
 
149
 
        // do we need to recalculate segment times?
150
 
        if( reset )
151
 
                calculateSegmentTimes();
152
 
 
153
 
        // wait till it's time to draw the next segment
154
 
        waitTillNextSegment( reset );
155
 
}