/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-17 13:11:02 UTC
  • Revision ID: edam@waxworlds.org-20111117131102-ihs5tz2hynj18h0r
moved schematic and Makefile to propeller-clock dir and updated Makefile for Arduino Pro Mini w/ Atmel 168 board

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
// number of segments in a full display (rotation) is 60 (one per
 
44
// second) times the desired number of sub-divisions of a second
 
45
#define NUM_SEGMENTS ( 60 * 5 )
 
46
 
 
47
 
 
48
//_____________________________________________________________________________
 
49
//                                                                         code
 
50
 
 
51
 
 
52
// ISR to handle the pulses from the fan's tachiometer
 
53
void fanPulseHandler()
 
54
{
 
55
        // the fan actually sends two pulses per revolution. These pulses
 
56
        // may not be exactly evenly distributed around the rotation, so
 
57
        // we can't recalculate times on every pulse. Instead, we ignore
 
58
        // every other pulse so timings are based on a complete rotation.
 
59
        static bool ignore = true;
 
60
        ignore = !ignore;
 
61
        if( !ignore )
 
62
        {
 
63
                // set a new pulse time
 
64
                new_pulse_at = micros();
 
65
        }
 
66
}
 
67
 
 
68
 
 
69
// draw a particular segment
 
70
void drawNextSegment( bool reset )
 
71
{
 
72
        static unsigned int segment = 0;
 
73
        if( reset ) segment = 0;
 
74
        segment++;
 
75
 
 
76
        for( int a = 0; a < 10; a++ )
 
77
                digitalWrite( a + 4, ( ( segment >> a ) & 1 )? HIGH : LOW );
 
78
}
 
79
 
 
80
 
 
81
// calculate time constants when a new pulse has occurred
 
82
void calculateSegmentTimes()
 
83
{
 
84
        // check for overflows, and only recalculate times if there isn't
 
85
        // one (if there is, we'll just go with the last pulse's times)
 
86
        if( new_pulse_at > last_pulse_at )
 
87
        {
 
88
                // new segment stepping times
 
89
                unsigned long delta = new_pulse_at - last_pulse_at;
 
90
                segment_step = delta / NUM_SEGMENTS;
 
91
                segment_step_sub = 0;
 
92
                segment_step_sub_step = delta % NUM_SEGMENTS;
 
93
        }
 
94
 
 
95
        // now we have dealt with this pulse, save the pulse time and
 
96
        // clear new_pulse_at, ready for the next pulse
 
97
        last_pulse_at = new_pulse_at;
 
98
        new_pulse_at = 0;
 
99
}
 
100
 
 
101
 
 
102
// wait until it is time to draw the next segment or a new pulse has
 
103
// occurred
 
104
void waitTillNextSegment( bool reset )
 
105
{
 
106
        static unsigned long end_time = 0;
 
107
 
 
108
        // handle reset
 
109
        if( reset )
 
110
                end_time = last_pulse_at;
 
111
 
 
112
        // work out the time that this segment should be displayed until
 
113
        end_time += segment_step;
 
114
        semgment_step_sub += semgment_step_sub_step;
 
115
        if( semgment_step_sub >= NUM_SEGMENTS ) {
 
116
                semgment_step_sub -= NUM_SEGMENTS;
 
117
                end_time++;
 
118
        }
 
119
 
 
120
        // wait
 
121
        while( micros() < end_time && !new_pulse_at );
 
122
}
 
123
 
 
124
 
 
125
// main setup
 
126
void setup()
 
127
{
 
128
        // set up an interrupt handler on pin 2 to nitice fan pulses
 
129
        attachInterrupt( 0, fanPulseHandler, RISING );
 
130
        digitalWrite( 2, HIGH );
 
131
  
 
132
        // set up output pins (4 to 13) for the led array
 
133
        for( int a = 4; a < 14; a++ )
 
134
                pinMode( a, OUTPUT );
 
135
 
 
136
        // serial comms
 
137
        Serial.begin( 9600 );
 
138
}
 
139
 
 
140
 
 
141
// main loop
 
142
void loop()
 
143
{
 
144
        // if there has been a new pulse, we'll be resetting the display
 
145
        bool reset = new_pulse_at? true : false;
 
146
 
 
147
        // draw this segment
 
148
        drawNextSegment( reset );
 
149
 
 
150
        // do we need to recalculate segment times?
 
151
        if( reset )
 
152
                calculateSegmentTimes();
 
153
 
 
154
        // wait till it's time to draw the next segment
 
155
        waitTillNextSegment( reset );
 
156
}