Gordons Projects

--> Projects Top-Level GIT

Removed some old files
[pibrella] / ladder.c
1 /*
2  * ladder.c:
3  *      Copyright (c) Gordon Henderson, June 2012-2014
4  ***********************************************************************
5  *    This is free software: you can redistribute it and/or modify
6  *    it under the terms of the GNU Lesser General Public License as published by
7  *    the Free Software Foundation, either version 3 of the License, or
8  *    (at your option) any later version.
9  *
10  *    This is distributed in the hope that it will be useful,
11  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *    GNU Lesser General Public License for more details.
14  *
15  *    You should have received a copy of the GNU Lesser General Public License
16  *    along with This.  If not, see <http://www.gnu.org/licenses/>.
17  ***********************************************************************
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <math.h>
24
25 #include <wiringPi.h>
26
27 #include "pibrella.h"
28
29 #ifndef TRUE
30 #  define       TRUE    (1==1)
31 #  define       FALSE   (1==2)
32 #endif
33
34 #undef  DEBUG
35
36 #define NUM_LEDS         7
37
38
39 // Map the LEDs to the hardware pins
40
41 const int ledMap [NUM_LEDS] =
42 {
43   PIBRELLA_OUT_3,
44   PIBRELLA_OUT_2,
45   PIBRELLA_OUT_1,
46   PIBRELLA_OUT_0,
47   PIBRELLA_GREEN,
48   PIBRELLA_YELLOW,
49   PIBRELLA_RED,
50 } ;
51
52
53 // Some constants for our circuit simulation
54
55 const double vBatt      =      9.0 ;    // Volts (ie. a PP3)
56 const double capacitor  =      0.001 ;  // 1000uF
57 const double rCharge    =   2200.0 ;    // ohms
58 const double rDischarge =  68000.0 ;    // ohms
59 const double timeInc    =      0.01 ;   // Seconds
60
61 double vCharge, vCap, vCapLast ;
62
63
64
65 /*
66  * setup:
67  *      Program the GPIO correctly and initialise the lamps
68  ***********************************************************************
69  */
70
71 void setup (void)
72 {
73   wiringPiSetup () ;
74   pibrellaSetup () ;
75
76 // Calculate the actual charging voltage - standard calculation of
77 //      vCharge = r2 / (r1 + r2) * vBatt
78 //
79 //
80 //   -----+--- vBatt
81 //        |
82 //        R1
83 //        |
84 //        +---+---- vCharge
85 //        |   |
86 //        R2  C
87 //        |   |
88 //   -----+---+-----
89
90   vCharge = rDischarge / (rCharge + rDischarge) * vBatt ;
91
92 // Start with no charge
93
94   vCap    = vCapLast = 0.0 ;
95 }
96
97
98 /*
99  * introLeds
100  *      Put a little pattern on the LEDs to start with
101  *********************************************************************************
102  */
103
104 void introLeds (void)
105 {
106   int i, j ;
107
108
109   printf ("Pi Ladder\n") ;
110   printf ("=========\n\n") ;
111   printf ("       vBatt: %6.2f volts\n", vBatt) ;
112   printf ("     rCharge: %6.0f ohms\n", rCharge) ;
113   printf ("  rDischarge: %6.0f ohms\n", rDischarge) ;
114   printf ("     vCharge: %6.2f volts\n", vCharge) ;
115   printf ("   capacitor: %6.0f uF\n", capacitor * 1000.0) ;
116
117 // Flash 3 times:
118
119   for (j = 0 ; j < 3 ; ++j)
120   {
121     for (i = 0 ; i < NUM_LEDS ; ++i)
122       digitalWrite (ledMap [i], 1) ;
123     delay (500) ;
124     for (i = 0 ; i < NUM_LEDS ; ++i)
125       digitalWrite (ledMap [i], 0) ;
126     delay (100) ;
127   }
128
129 // All On
130
131   for (i = 0 ; i < NUM_LEDS ; ++i)
132     digitalWrite (ledMap [i], 1) ;
133   delay (500) ;
134
135 // Countdown...
136
137   for (i = NUM_LEDS - 1 ; i >= 0 ; --i)
138   {
139     digitalWrite (ledMap [i], 0) ;
140     delay (100) ;
141   }
142   delay (500) ;
143 }
144
145
146 /*
147  * winningLeds
148  *      Put a little pattern on the LEDs to start with
149  *********************************************************************************
150  */
151
152 void winningLeds (void)
153 {
154   int i, j ;
155
156 // Flash 3 times:
157
158   for (j = 0 ; j < 3 ; ++j)
159   {
160     for (i = 0 ; i < NUM_LEDS ; ++i)
161       digitalWrite (ledMap [i], 1) ;
162     delay (500) ;
163     for (i = 0 ; i < NUM_LEDS ; ++i)
164       digitalWrite (ledMap [i], 0) ;
165     delay (100) ;
166   }
167
168 // All On
169
170   for (i = 0 ; i < NUM_LEDS ; ++i)
171     digitalWrite (ledMap [i], 1) ;
172   delay (500) ;
173
174 // Countup...
175
176   for (i = 0 ; i < NUM_LEDS ; ++i)
177   {
178     digitalWrite (ledMap [i], 0) ;
179     delay (100) ;
180   }
181   delay (500) ;
182 }
183
184
185 /*
186  * chargeCapacitor: dischargeCapacitor:
187  *      Add or remove charge to the capacitor.
188  *      Standard capacitor formulae.
189  *********************************************************************************
190  */
191
192 void chargeCapacitor (void)
193 {
194   vCap = (vCapLast - vCharge) *
195         exp (- timeInc / (rCharge * capacitor)) + vCharge ;
196
197 #ifdef  DEBUG
198   printf ("+vCap: %7.4f\n", vCap) ;
199 #endif
200
201   vCapLast = vCap ;
202 }
203
204 void dischargeCapacitor (void)
205 {
206   vCap = vCapLast *
207         exp (- timeInc / (rDischarge * capacitor)) ;
208
209 #ifdef  DEBUG
210   printf ("-vCap: %7.4f\n", vCap) ;
211 #endif
212
213   vCapLast = vCap ;
214 }
215
216
217 /*
218  * ledBargraph:
219  *      Output the supplied number as a bargraph on the LEDs
220  *********************************************************************************
221  */
222
223 void ledBargraph (double value, int topLedOn)
224 {
225   int topLed = (int)floor (value / vCharge * (double)NUM_LEDS) + 1 ;
226   int i ;
227
228   if (topLed > NUM_LEDS)
229     topLed = NUM_LEDS ;
230
231   if (!topLedOn)
232     --topLed ;
233
234   for (i = 0 ; i < topLed ; ++i)
235     digitalWrite (ledMap [i], 1) ;
236
237   for (i = topLed ; i < NUM_LEDS ; ++i)
238     digitalWrite (ledMap [i], 0) ;
239 }
240
241
242 /*
243  * ledOnAction:
244  *      Make sure the leading LED is on and check the button
245  *********************************************************************************
246  */
247
248 void ledOnAction (void)
249 {
250   if (digitalRead (PIBRELLA_BUTTON) == HIGH)
251   {
252     chargeCapacitor () ;
253     ledBargraph (vCap, TRUE) ;
254   }
255 }
256
257
258 /*
259  * ledOffAction:
260  *      Make sure the leading LED is off and check the button
261  *********************************************************************************
262  */
263
264 void ledOffAction (void)
265 {
266   dischargeCapacitor () ;
267
268 // Are we still pushing the button?
269
270   if (digitalRead (PIBRELLA_BUTTON) == HIGH)
271   {
272     vCap = vCapLast = 0.0 ;
273     ledBargraph (vCap, FALSE) ;
274
275 // Wait until we release the button
276
277     while (digitalRead (PIBRELLA_BUTTON) == HIGH)
278       delay (10) ;
279   }
280 }
281
282
283 /*
284  ***********************************************************************
285  * The main program
286  ***********************************************************************
287  */
288
289 int main (void)
290 {
291   unsigned int then, ledOnTime, ledOffTime ;
292   unsigned int ourDelay = (int)(1000.0 * timeInc) ;
293   
294   setup     () ;
295   introLeds () ;
296
297 // Setup the LED times - TODO reduce the ON time as the game progresses
298
299   ledOnTime  = 1000 ;
300   ledOffTime = 1000 ;
301
302 // This is our Gate/Squarewave loop
303
304   for (;;)
305   {
306
307 // LED ON:
308
309     (void)ledBargraph (vCap, TRUE) ;
310     then = millis () + ledOnTime ;
311     while (millis () < then)
312     {
313       ledOnAction () ;
314       delay       (ourDelay) ;
315     }
316
317 // Have we won yet?
318 //      We need vCap to be in the top NUM_LEDS of the vCharge
319
320     if (vCap > ((double)(NUM_LEDS - 1) / (double)NUM_LEDS * vCharge))   // Woo hoo!
321     {
322       winningLeds () ;
323       while (digitalRead (PIBRELLA_BUTTON) == LOW)
324         delay (10) ;
325       while (digitalRead (PIBRELLA_BUTTON) == HIGH)
326         delay (10) ;
327       vCap = vCapLast = 0.0 ;
328     }
329
330 // LED OFF:
331
332     (void)ledBargraph (vCap, FALSE) ;
333     then = millis () + ledOffTime ;
334     while (millis () < then)
335     {
336       ledOffAction () ;
337       delay        (ourDelay) ;
338     }
339
340   }
341
342   return 0 ;
343 }