The Intro:

This Exercise Clock was created as a final project submission for CMU Ideate’s Physical Computing class. Our prompt was to meet with an older person in our community (selected for us from CMU’s OSHER classes) and create an assistive device personalized to them.

Our group was paired with Jan, and through our previous discussions with her, we learned that she enjoyed going on walks, but felt that she wasn’t as active as she should be. Since she didn’t care for the exercise apps she had tried, we created a prototype clock for her to use to track her physical activity.

We then finalized the project with this version, according to Jan’s feedback to the prototype.

The Product:

Our final product is a clock that reminds Jan to exercise and keeps track of how long she exercises. The clock cycles between three screens,  the first displays the time and date, the second displays bar graph of how long Jan exercised each day for the past two weeks, and the third compares the time Jan spent exercising the current week and last week. There is also a row of LEDs that display how many days from the past week that Jan has exercised. If Jan hasn’t met her exercise goal for the day, the clock will beep every hour if it senses someone in the room. When the button is pressed, the screen displays a timer.  When the button is pressed again, the timer is turned off and the time is added to the graph and if the exercise goal is met, one of the LEDs turns on. There is also a mute switch that puts makes the screen dim and makes the clock stop beeping.

Overall Photo:

An overall photo of our final product.

Basic Operation:

Pressing the button to start and stop the timer.

Twisting the button to set the time.

Flipping the mute switch on and off.

Detail Photos:

The display showing the time and date.

The display showing the graph of time spent exercising for the past two weeks.

The display comparing the amount of exercise this week and last week.

The display when the clock is in muted mode.

The LED row with one LED on, and the motion sensor.

The speaker and the off switch.

Usage Photos:

Pressing the button to stop the timer.

Turning the button to set the time and date.

Flipping the switch and putting the clock in muted mode.

The Process:

Following the formative critique, we created a schedule to guide us through the remainder of the project.

After completing our prototype we created this plan to finish the project.

Our first tasks were to complete the functionality of the device, and we were able to stay on schedule while doing so.

We wanted Jan to be able to view her recent workout history from a distance.   Our group decided to use a row of 7 Red-Green LED’s on our reminder clock to display the information in an manner that was easily noticeable but not out of place in her kitchen.  Each Red-Green LED would represent a day in the past week, appearing green if she worked out but red otherwise.  The easiest way to attach these lights would be with one pin per color for every light, which would use 14 pins.   However, due to the limited number of outputs on the Arduino we needed to condense this feature into just 7 pins.  To achieve this goal, we took advantage of each light only needing to be red or green at a certain time and used transistors to select between the two options with a single pin.   We also ran into early problems powering all 7 Red-Green LEDs at once, but using the 5v pin as the main power source for the lights fixed this problem for the time being.

Initial ideas for reducing the number of pins needed for the LEDs.

Our final circuit for the Red-Green LEDs.

Furthermore, Jan mentioned multiple features that she believed would improve her experience with the device.  She worried that the clock would continue to provide alerts while she was out of town with her neighbor looking after the house.  Our group decided to include a mute switch which dimmed the screen and stopped alerts in this situation.  She also expressed multiple concerns about the longevity of the device, so we decided on several changes to improve this area.  We added a more precise time keeping element, so the clock would skew less overtime.  In software, we fixed bugs that would occur when the date had an overflow error.  Also, for any unexpected errors ,as well as daylight savings time and leap years, we added the ability to change the time and date manually.  This feature required a new input to choose between times, so we changed the button on the device into a rotary encoder to increase the functionality while keeping the interface minimal.

The rotary encoder we replaced our button with to enable the time changing functionality.

A test of changes we made to our code to prevent overflow errors.

After completing the functionality of the reminder clock we began to assemble the final product, but the construction took longer then we anticipated.  We originally planned to finish before Thanksgiving break, but our group had to do considerable work after we returned.  This delay was largely due to us underestimating the work needed to finish the case.  When initially designing the outside, we combined math and intuition to create an overall shape.  We wanted the device to be large enough to sit between two wall trims without leaving too much space, and the top to be at an angle that she could easily view while standing.

A sketch used in deciding the angle of the clock’s top.

Our first setback in manufacturing occurred when choosing how to assemble the case.  We originally designed a file to 3d print, but afterwards decided to change to laser engraving due to size constraints on the 3d printer.  When we tried to assemble our final box our group faced multiple other issues.  We decided to use a “5 minute” epoxy to connect the pieces.  However, we did not mix the components correctly, which created a messy layer of residue on our product.  This initial failure made later attempts to glue box less effective, as the original epoxy blocked the new adhesive.  Later, when putting components into the box, we accidentally shattered one of the sides.  These two errors led to us re-engraving the case.  The second time was much neater, as we were more careful and used acrylic glue.

A cardboard prototype of our box used to optimize hole sizes before our final print.

A shattered side of our box after a panel mounting accident.

Unfortunately, when assembling the final circuitry using an Arduino nano we ran into a problem powering all 7 LEDs similar to our earlier issue.  This time, however, our solution of using the 5v pin as the main power source for the lights was not working.  Since we had fallen behind schedule, we did not have time to solve this problem, so we decided to replace the Red-Green LEDs with normal LEDs for our final clock.

The Red-Green LEDs were replaced with simple blue LEDs due to problems when making the final circuitry.

The Feedback:

Our project received mostly positive feedback, though, some valid criticisms and suggestions were raised. One commenter noted, for example, that

“LED lights + day of week on display should go in same direction”

in reference to the fact that our LED display on the front of the device represented the most recent day on the left of the device, while our bargraph on the LCD had  the most recent day on the right. This is an aspect of the device we hadn’t noticed, however changing it did make the different displays of the device more intuitive to comprehend at a glance.

Another comment we received regarded the physical presence of the device:

“Consider making the knob a bit bigger – it might make it easier to use.”

As a group, we also agreed with this criticism, to the extent that we were originally planning to make the knob much larger than it is currently in our final project. While unfortunately we weren’t able to get the custom part created in time, Jan at least seemed pleased with the replacement knob we did end up using.

One of the most important things we learned while creating something for another person, is the importance of listening. Many of the design choices we made to customize this clock for Jan were the result of minor comments she made during the interview process. Things like the size of the device, and our method of interaction we as effective as they could be because we noted specifically how Jan expected to use the device.  If we were to do this project another time, we would most likely pay more attention to the physical for and aesthetics of the device earlier in the design process, to ensure we wouldn’t have another plastic box panic the night before the project was due.

If we were to do this project again, one of the most useful modifications to the design process would be to include some time for “beta testing.” While we were able to demonstrate a prototype of our project to Jan to get some basic feedback, the feedback we got was somewhat limited in that we collected it in a classroom setting. Being able to let Jan take the device home with her for a few days of testing could potentially bring light to some more minor issues which we wouldn’t be able to discover within a classroom environment.

The Details:

The electrical schematic of our project.

The Code:

  1. <span class="com">/*
  2. * Workout_Clock.ino
  3. *
  4. * Exercise Reminder Clock
  5. * Karen Abruzzo, Justin Kiefel, George Ralph
  6. *
  7. * This code runs a clock, which can be used to track the duration of
  8. * exercise intervals with stopwatch-like functionality whenever TIMER_BUT_PIN
  9. * is pressed. The clock also tracks exercise history over a 2 week period,
  10. * and reminds the user through audio tones to exercise whenever they are
  11. * detected by the motion sensor. (Though this feature can be disabled)
  12. *
  13. * Inputs
  14. * 0 - Motion Sensor
  15. * 2 - Rotary Encoder Clock Pin
  16. * 3 - Rotary Encoder Data Pin
  17. * 4 - Rotary Encoder Button
  18. * 5 - Power/Mute Switch
  19. *
  20. * Outputs
  21. * 6 - Speaker Pin
  22. * 7..13 - Bargraph LEDs
  23. *
  24. * Outputs
  25. *
  26. * NOTE: This project must be compiled with compiler warnings disabled due to
  27. * aspects of the libraries we use, which are beyond our control.
  28. */</span><span class="pln">
  29. </span><span class="com">#include</span><span class="pln"> </span><span class="str"><Encoder.h></span><span class="pln">
  30. </span><span class="com">#include</span><span class="pln"> </span><span class="str"><Wire.h></span><span class="pln">
  31. </span><span class="com">#include</span><span class="pln"> </span><span class="str"><DS3231M.h></span><span class="pln"> </span><span class="com">//library for the rtc</span><span class="pln">
  32. </span><span class="com">#include</span><span class="pln"> </span><span class="str"><LiquidCrystal_I2C.h></span><span class="pln">
  33. </span><span class="com">#include</span><span class="pln"> </span><span class="str">"pitches.h"</span><span class="pln">
  34. </span><span class="com">/* Create an LCD display object called "screen" with I2C address 0x27
  35. which is 20 columns wide and 4 rows tall. You can use any name you'd like. */</span><span class="pln">
  36. </span><span class="typ">LiquidCrystal_I2C</span><span class="pln"> screen</span><span class="pun">(</span><span class="lit">0x27</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">);</span><span class="pln">
  37. DS3231M_Class DS3231M</span><span class="pun">;</span><span class="pln">
  38. </span><span class="com">//Make buffer size the size of the screen area, just to be safe</span><span class="pln">
  39. </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">uint8_t</span><span class="pln"> SPRINTF_BUFFER_SIZE </span><span class="pun">=</span><span class="pln"> </span><span class="lit">80</span><span class="pun">;</span><span class="pln">
  40. </span><span class="kwd">char</span><span class="pln"> inputBuffer</span><span class="pun">[</span><span class="pln">SPRINTF_BUFFER_SIZE</span><span class="pun">];</span><span class="pln">
  41. </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">uint32_t</span><span class="pln"> SERIAL_SPEED </span><span class="pun">=</span><span class="pln"> </span><span class="lit">115200</span><span class="pun">;</span><span class="pln">
  42. </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> MOTION_PIN </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  43. </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> ENC_CLK_PIN </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
  44. </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> ENC_DT_PIN </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">
  45. </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> TIMER_BUT_PIN </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pun">;</span><span class="pln">
  46. </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> POWER_SWITCH </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
  47. </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> SPEAKER_PIN </span><span class="pun">=</span><span class="pln"> </span><span class="lit">6</span><span class="pun">;</span><span class="pln">
  48. </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> LED_BASE_PIN </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pun">;</span><span class="pln">
  49. </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> LED_CNT </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pun">;</span><span class="pln">
  50. </span><span class="com">//Goal time is 40 minutes</span><span class="pln">
  51. </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> GOAL_TIME </span><span class="pun">=</span><span class="pln"> </span><span class="lit">60</span><span class="pun">*</span><span class="lit">40</span><span class="pun">;</span><span class="pln">
  52. </span><span class="typ">Encoder</span><span class="pln"> enc</span><span class="pun">(</span><span class="pln">ENC_CLK_PIN</span><span class="pun">,</span><span class="pln"> ENC_DT_PIN</span><span class="pun">);</span><span class="pln">
  53. </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> weekLetters</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="str">'S'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'M'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'T'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'W'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'H'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'F'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'S'</span><span class="pun">};</span><span class="pln">
  54. </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> weekDays</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="str">"Sunday"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Monday"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Tuesday"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Wednesday"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Thursday"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Friday"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Saturday"</span><span class="pun">};</span><span class="pln">
  55. </span><span class="com">// 2 = half note, 4 = quarter note, ect.</span><span class="pln">
  56. </span><span class="kwd">int</span><span class="pln"> openSound</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> NOTE_B3</span><span class="pun">,</span><span class="pln"> NOTE_B4</span><span class="pun">};</span><span class="pln">
  57. </span><span class="kwd">int</span><span class="pln"> workoutSound</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16</span><span class="pun">,</span><span class="pln"> NOTE_B3</span><span class="pun">,</span><span class="pln"> NOTE_B5</span><span class="pun">};</span><span class="pln">
  58. </span><span class="kwd">int</span><span class="pln"> clockSound</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> NOTE_A5</span><span class="pun">};</span><span class="pln">
  59. </span><span class="kwd">int</span><span class="pln"> sadSound</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> NOTE_F3</span><span class="pun">,</span><span class="pln"> NOTE_C3</span><span class="pun">};</span><span class="pln">
  60. </span><span class="kwd">int</span><span class="pln"> happySound</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> NOTE_C4</span><span class="pun">,</span><span class="pln"> NOTE_E4</span><span class="pun">,</span><span class="pln"> NOTE_G4</span><span class="pun">,</span><span class="pln"> NOTE_C5</span><span class="pun">};</span><span class="pln">
  61. </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> start</span><span class="pun">;</span><span class="pln">
  62. </span><span class="kwd">bool</span><span class="pln"> timerOn </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  63. </span><span class="kwd">int</span><span class="pln"> pastTimes</span><span class="pun">[</span><span class="lit">28</span><span class="pun">];</span><span class="pln">
  64. </span><span class="kwd">int</span><span class="pln"> timeSeconds</span><span class="pun">;</span><span class="pln">
  65. </span><span class="kwd">boolean</span><span class="pln"> isMidnight </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
  66. </span><span class="kwd">long</span><span class="pln"> lastPing </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  67. </span><span class="kwd">long</span><span class="pln"> pingTimeout </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3600</span><span class="pun">;</span><span class="pln">
  68. </span><span class="kwd">bool</span><span class="pln"> advancePast </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
  69. </span><span class="kwd">bool</span><span class="pln"> timerPast </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
  70. </span><span class="kwd">long</span><span class="pln"> updateTime</span><span class="pun">,</span><span class="pln"> buttonDownTime</span><span class="pun">;</span><span class="pln">
  71. </span><span class="kwd">int</span><span class="pln"> screenState </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  72. </span><span class="kwd">bool</span><span class="pln"> pastPowerState </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
  73. </span><span class="kwd">bool</span><span class="pln"> powerState </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
  74. </span><span class="kwd">void</span><span class="pln"> setup</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  75. </span><span class="com">// Initialize pins</span><span class="pln">
  76. pinMode</span><span class="pun">(</span><span class="pln">TIMER_BUT_PIN</span><span class="pun">,</span><span class="pln"> INPUT_PULLUP</span><span class="pun">);</span><span class="pln">
  77. pinMode</span><span class="pun">(</span><span class="pln">POWER_SWITCH</span><span class="pun">,</span><span class="pln"> INPUT_PULLUP</span><span class="pun">);</span><span class="pln">
  78. pinMode</span><span class="pun">(</span><span class="pln">SPEAKER_PIN</span><span class="pun">,</span><span class="pln"> OUTPUT</span><span class="pun">);</span><span class="pln">
  79. pinMode</span><span class="pun">(</span><span class="pln">MOTION_PIN</span><span class="pun">,</span><span class="pln"> INPUT</span><span class="pun">);</span><span class="pln">
  80. digitalWrite</span><span class="pun">(</span><span class="pln">SPEAKER_PIN</span><span class="pun">,</span><span class="pln"> LOW</span><span class="pun">);</span><span class="pln">
  81. </span><span class="com">//Initialize the LED pins as a consecutive block of pins</span><span class="pln">
  82. </span><span class="kwd">for</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> LED_CNT</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  83. pinMode</span><span class="pun">(</span><span class="pln">LED_BASE_PIN </span><span class="pun">+</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> OUTPUT</span><span class="pun">);</span><span class="pln">
  84. </span><span class="pun">}</span><span class="pln">
  85. </span><span class="com">//setup pins</span><span class="pln">
  86. </span><span class="com">//Serial.begin(SERIAL_SPEED);</span><span class="pln">
  87. </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">DS3231M</span><span class="pun">.</span><span class="kwd">begin</span><span class="pun">())</span><span class="pln">
  88. </span><span class="pun">{</span><span class="pln">
  89. </span><span class="com">//Serial.println(F("Unable to find DS3231MM. Checking again in 3s."));</span><span class="pln">
  90. delay</span><span class="pun">(</span><span class="lit">3000</span><span class="pun">);</span><span class="pln">
  91. </span><span class="pun">}</span><span class="pln">
  92. </span><span class="com">// initialize the screen (only need to do this once)</span><span class="pln">
  93. screen</span><span class="pun">.</span><span class="pln">init</span><span class="pun">();</span><span class="pln">
  94. screen</span><span class="pun">.</span><span class="pln">backlight</span><span class="pun">();</span><span class="pln">
  95. powerState </span><span class="pun">=</span><span class="pln"> </span><span class="pun">!</span><span class="pln">digitalRead</span><span class="pun">(</span><span class="pln">POWER_SWITCH</span><span class="pun">);</span><span class="pln">
  96. pastPowerState </span><span class="pun">=</span><span class="pln"> powerState</span><span class="pun">;</span><span class="pln">
  97. </span><span class="typ">DateTime</span><span class="pln"> now </span><span class="pun">=</span><span class="pln"> DS3231M</span><span class="pun">.</span><span class="pln">now</span><span class="pun">();</span><span class="pln">
  98. lastPing </span><span class="pun">=</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">unixtime</span><span class="pun">();</span><span class="pln">
  99. updateTime </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">();</span><span class="pln">
  100. </span><span class="com">//setTime();</span><span class="pln">
  101. </span><span class="pun">}</span><span class="pln">
  102. </span><span class="kwd">void</span><span class="pln"> loop</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  103. </span><span class="kwd">bool</span><span class="pln"> timerState </span><span class="pun">=</span><span class="pln"> </span><span class="pun">!</span><span class="pln">digitalRead</span><span class="pun">(</span><span class="pln">TIMER_BUT_PIN</span><span class="pun">);</span><span class="pln">
  104. </span><span class="kwd">bool</span><span class="pln"> powerState </span><span class="pun">=</span><span class="pln"> </span><span class="pun">!</span><span class="pln">digitalRead</span><span class="pun">(</span><span class="pln">POWER_SWITCH</span><span class="pun">);</span><span class="pln">
  105. </span><span class="com">//On button down</span><span class="pln">
  106. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">timerState </span><span class="pun">&&</span><span class="pln"> </span><span class="pun">!</span><span class="pln">timerPast</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  107. buttonDownTime </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">();</span><span class="pln">
  108. </span><span class="pun">}</span><span class="pln">
  109. </span><span class="com">//On button up</span><span class="pln">
  110. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">timerState </span><span class="pun">&&</span><span class="pln"> timerPast</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  111. </span><span class="com">//If the button has been down for more than a second</span><span class="pln">
  112. </span><span class="com">//Enter settings dialog</span><span class="pln">
  113. </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">buttonDownTime </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1000</span><span class="pln"> </span><span class="pun"><=</span><span class="pln"> millis</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  114. setTime</span><span class="pun">();</span><span class="pln">
  115. </span><span class="pun">}</span><span class="pln">
  116. </span><span class="kwd">else</span><span class="pln">
  117. </span><span class="com">//Otherwise, start the timer</span><span class="pln">
  118. </span><span class="pun">{</span><span class="pln">
  119. timer</span><span class="pun">();</span><span class="pln">
  120. </span><span class="pun">}</span><span class="pln">
  121. updateTime </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">3000</span><span class="pun">;</span><span class="pln">
  122. </span><span class="pun">}</span><span class="pln">
  123. </span><span class="com">//In timer mode, draw the elapsed time so far</span><span class="pln">
  124. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">timerOn</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  125. </span><span class="com">//But only, once a second</span><span class="pln">
  126. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">((</span><span class="pln">updateTime </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">)</span><span class="pln"> </span><span class="pun"><=</span><span class="pln"> millis</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  127. drawTimer</span><span class="pun">();</span><span class="pln">
  128. updateTime </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">();</span><span class="pln">
  129. </span><span class="pun">}</span><span class="pln">
  130. </span><span class="pun">}</span><span class="pln">
  131. </span><span class="kwd">else</span><span class="pln">
  132. </span><span class="pun">{</span><span class="pln">
  133. </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">powerState</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  134. </span><span class="com">//Cycle the screen every 3 seconds when power is on</span><span class="pln">
  135. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">((</span><span class="pln">updateTime </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3000</span><span class="pun">)</span><span class="pln"> </span><span class="pun"><=</span><span class="pln"> millis</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  136. </span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">screenState</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  137. </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
  138. drawHome</span><span class="pun">();</span><span class="pln">
  139. </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  140. </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
  141. drawWeekCompare</span><span class="pun">(</span><span class="pln">getTotalTime</span><span class="pun">(</span><span class="lit">14</span><span class="pun">,</span><span class="pln"> </span><span class="lit">21</span><span class="pun">),</span><span class="pln"> getTotalTime</span><span class="pun">(</span><span class="lit">21</span><span class="pun">,</span><span class="pln"> </span><span class="lit">28</span><span class="pun">));</span><span class="pln">
  142. </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  143. </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
  144. drawTwoWeekGraph</span><span class="pun">(</span><span class="pln">pastTimes</span><span class="pun">);</span><span class="pln">
  145. </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
  146. </span><span class="pun">}</span><span class="pln">
  147. updateTime </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">();</span><span class="pln">
  148. screenState </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">screenState </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">
  149. </span><span class="pun">}</span><span class="pln">
  150. </span><span class="pun">}</span><span class="pln">
  151. </span><span class="kwd">else</span><span class="pln">
  152. </span><span class="pun">{</span><span class="pln">
  153. </span><span class="com">//Update the clock every few seconds when power is off</span><span class="pln">
  154. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">((</span><span class="pln">updateTime </span><span class="pun">+</span><span class="pln"> </span><span class="lit">5000</span><span class="pun">)</span><span class="pln"> </span><span class="pun"><=</span><span class="pln"> millis</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  155. drawHome</span><span class="pun">();</span><span class="pln">
  156. updateTime </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">();</span><span class="pln">
  157. </span><span class="pun">}</span><span class="pln">
  158. </span><span class="pun">}</span><span class="pln">
  159. </span><span class="com">//If no time is logged for today (and device is on)</span><span class="pln">
  160. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">pastTimes</span><span class="pun">[</span><span class="lit">27</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">&&</span><span class="pln"> powerState</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  161. </span><span class="com">//If the motion sensor detects motion</span><span class="pln">
  162. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">digitalRead</span><span class="pun">(</span><span class="pln">MOTION_PIN</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  163. </span><span class="com">//If it's been a while since we last pinged</span><span class="pln">
  164. </span><span class="typ">DateTime</span><span class="pln"> now </span><span class="pun">=</span><span class="pln"> DS3231M</span><span class="pun">.</span><span class="pln">now</span><span class="pun">();</span><span class="pln">
  165. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">now</span><span class="pun">.</span><span class="pln">unixtime</span><span class="pun">()</span><span class="pln"> </span><span class="pun">>=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">lastPing </span><span class="pun">+</span><span class="pln"> pingTimeout</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  166. </span><span class="com">//Ping the user</span><span class="pln">
  167. playSound</span><span class="pun">(</span><span class="pln">sadSound</span><span class="pun">);</span><span class="pln">
  168. lastPing </span><span class="pun">=</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">unixtime</span><span class="pun">();</span><span class="pln">
  169. </span><span class="pun">}</span><span class="pln">
  170. </span><span class="pun">}</span><span class="pln">
  171. </span><span class="pun">}</span><span class="pln">
  172. </span><span class="pun">}</span><span class="pln">
  173. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">isNewDay</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&&</span><span class="pln"> </span><span class="pun">!</span><span class="pln">isMidnight</span><span class="pun">)</span><span class="pln">
  174. </span><span class="pun">{</span><span class="pln">
  175. newDaySetup</span><span class="pun">();</span><span class="pln">
  176. isMidnight </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
  177. </span><span class="pun">}</span><span class="pln">
  178. updateLEDs</span><span class="pun">();</span><span class="pln">
  179. </span><span class="com">//Turn the screen on/off if the power switch is flipped</span><span class="pln">
  180. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">powerState </span><span class="pun">!=</span><span class="pln"> pastPowerState</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  181. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">powerState</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  182. screen</span><span class="pun">.</span><span class="pln">backlight</span><span class="pun">();</span><span class="pln">
  183. updateTime </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">();</span><span class="pln">
  184. </span><span class="pun">}</span><span class="pln">
  185. </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  186. screen</span><span class="pun">.</span><span class="pln">noBacklight</span><span class="pun">();</span><span class="pln">
  187. screenState </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  188. drawHome</span><span class="pun">();</span><span class="pln">
  189. </span><span class="pun">}</span><span class="pln">
  190. </span><span class="pun">}</span><span class="pln">
  191. pastPowerState </span><span class="pun">=</span><span class="pln"> powerState</span><span class="pun">;</span><span class="pln">
  192. timerPast </span><span class="pun">=</span><span class="pln"> timerState</span><span class="pun">;</span><span class="pln">
  193. </span><span class="pun">}</span><span class="pln">
  194. </span><span class="com">/* The time-setting dialog menu */</span><span class="pln">
  195. </span><span class="kwd">void</span><span class="pln"> setTime</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  196. screen</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">
  197. </span><span class="com">//Grab the current time</span><span class="pln">
  198. </span><span class="typ">DateTime</span><span class="pln"> now </span><span class="pun">=</span><span class="pln"> DS3231M</span><span class="pun">.</span><span class="pln">now</span><span class="pun">();</span><span class="pln">
  199. </span><span class="kwd">int</span><span class="pln"> hour </span><span class="pun">=</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">hour</span><span class="pun">();</span><span class="pln">
  200. </span><span class="kwd">int</span><span class="pln"> minute </span><span class="pun">=</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">minute</span><span class="pun">();</span><span class="pln">
  201. </span><span class="kwd">int</span><span class="pln"> day </span><span class="pun">=</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">day</span><span class="pun">();</span><span class="pln">
  202. </span><span class="kwd">int</span><span class="pln"> month </span><span class="pun">=</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">month</span><span class="pun">();</span><span class="pln">
  203. </span><span class="kwd">int</span><span class="pln"> year </span><span class="pun">=</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">year</span><span class="pun">();</span><span class="pln">
  204. </span><span class="com">//Initialize buffers to print before and after the number we choose</span><span class="pln">
  205. </span><span class="kwd">char</span><span class="pln"> beforeBuffer</span><span class="pun">[</span><span class="pln">SPRINTF_BUFFER_SIZE</span><span class="pun">];</span><span class="pln">
  206. </span><span class="kwd">char</span><span class="pln"> afterBuffer</span><span class="pun">[</span><span class="pln">SPRINTF_BUFFER_SIZE</span><span class="pun">];</span><span class="pln">
  207. </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> header </span><span class="pun">=</span><span class="pln"> </span><span class="str">" Set Time "</span><span class="pun">;</span><span class="pln">
  208. </span><span class="com">//For each time, format the string around it with the previously set time</span><span class="pln">
  209. sprintf</span><span class="pun">(</span><span class="pln">beforeBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%s ("</span><span class="pun">,</span><span class="pln"> header</span><span class="pun">);</span><span class="pln">
  210. sprintf</span><span class="pun">(</span><span class="pln">afterBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">"):%02d %d/%02d/%04d"</span><span class="pun">,</span><span class="pln"> minute</span><span class="pun">,</span><span class="pln"> month</span><span class="pun">,</span><span class="pln"> day</span><span class="pun">,</span><span class="pln"> year</span><span class="pun">);</span><span class="pln">
  211. hour </span><span class="pun">=</span><span class="pln"> getNumInput</span><span class="pun">(</span><span class="lit">24</span><span class="pun">,</span><span class="pln"> beforeBuffer</span><span class="pun">,</span><span class="pln"> afterBuffer</span><span class="pun">,</span><span class="pln"> hour</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
  212. sprintf</span><span class="pun">(</span><span class="pln">beforeBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%s %2d:("</span><span class="pun">,</span><span class="pln"> header</span><span class="pun">,</span><span class="pln"> hour</span><span class="pun">);</span><span class="pln">
  213. sprintf</span><span class="pun">(</span><span class="pln">afterBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">") %d/%02d/%04d"</span><span class="pun">,</span><span class="pln"> month</span><span class="pun">,</span><span class="pln"> day</span><span class="pun">,</span><span class="pln"> year</span><span class="pun">);</span><span class="pln">
  214. minute </span><span class="pun">=</span><span class="pln"> getNumInput</span><span class="pun">(</span><span class="lit">60</span><span class="pun">,</span><span class="pln"> beforeBuffer</span><span class="pun">,</span><span class="pln"> afterBuffer</span><span class="pun">,</span><span class="pln"> minute</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
  215. sprintf</span><span class="pun">(</span><span class="pln">beforeBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%s %2d:%02d ("</span><span class="pun">,</span><span class="pln"> header</span><span class="pun">,</span><span class="pln"> hour</span><span class="pun">,</span><span class="pln"> minute</span><span class="pun">);</span><span class="pln">
  216. sprintf</span><span class="pun">(</span><span class="pln">afterBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">")/%02d/%04d"</span><span class="pun">,</span><span class="pln"> day</span><span class="pun">,</span><span class="pln"> year</span><span class="pun">);</span><span class="pln">
  217. month </span><span class="pun">=</span><span class="pln"> getNumInput</span><span class="pun">(</span><span class="lit">12</span><span class="pun">,</span><span class="pln"> beforeBuffer</span><span class="pun">,</span><span class="pln"> afterBuffer</span><span class="pun">,</span><span class="pln"> month</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
  218. sprintf</span><span class="pun">(</span><span class="pln">beforeBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%s %2d:%02d %2d/("</span><span class="pun">,</span><span class="pln"> header</span><span class="pun">,</span><span class="pln"> hour</span><span class="pun">,</span><span class="pln"> minute</span><span class="pun">,</span><span class="pln"> month</span><span class="pun">);</span><span class="pln">
  219. sprintf</span><span class="pun">(</span><span class="pln">afterBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">")/%04d"</span><span class="pun">,</span><span class="pln"> year</span><span class="pun">);</span><span class="pln">
  220. day </span><span class="pun">=</span><span class="pln"> getNumInput</span><span class="pun">(</span><span class="lit">31</span><span class="pun">,</span><span class="pln"> beforeBuffer</span><span class="pun">,</span><span class="pln"> afterBuffer</span><span class="pun">,</span><span class="pln"> day</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
  221. sprintf</span><span class="pun">(</span><span class="pln">beforeBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%s %2d:%02d %2d/%02d/("</span><span class="pun">,</span><span class="pln"> header</span><span class="pun">,</span><span class="pln"> hour</span><span class="pun">,</span><span class="pln"> minute</span><span class="pun">,</span><span class="pln"> month</span><span class="pun">,</span><span class="pln"> day</span><span class="pun">);</span><span class="pln">
  222. sprintf</span><span class="pun">(</span><span class="pln">afterBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">")"</span><span class="pun">);</span><span class="pln">
  223. year </span><span class="pun">=</span><span class="pln"> getNumInput</span><span class="pun">(</span><span class="lit">10000</span><span class="pun">,</span><span class="pln"> beforeBuffer</span><span class="pun">,</span><span class="pln"> afterBuffer</span><span class="pun">,</span><span class="pln"> year</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
  224. </span><span class="typ">DateTime</span><span class="pln"> newTime </span><span class="pun">=</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">(</span><span class="pln">year</span><span class="pun">,</span><span class="pln"> month</span><span class="pun">,</span><span class="pln"> day</span><span class="pun">,</span><span class="pln"> hour</span><span class="pun">,</span><span class="pln"> minute</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
  225. DS3231M</span><span class="pun">.</span><span class="pln">adjust</span><span class="pun">(</span><span class="pln">newTime</span><span class="pun">);</span><span class="pln">
  226. </span><span class="com">//Make sure we show the clock screen after this</span><span class="pln">
  227. screenState </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  228. </span><span class="pun">}</span><span class="pln">
  229. </span><span class="com">/* Creates a number input dialog, with strings before and after the number
  230. An initial value can be specified,
  231. Input is modular about bound (ie 60 for values 0-59)
  232. The bound range can be offset via minOffset (ie 1 for 1-60 in the above example) */</span><span class="pln">
  233. </span><span class="kwd">int</span><span class="pln"> getNumInput</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> bound</span><span class="pun">,</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> before</span><span class="pun">,</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> after</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> initial</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> minOffset</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  234. </span><span class="kwd">int</span><span class="pln"> </span><span class="kwd">value</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  235. </span><span class="kwd">int</span><span class="pln"> offset </span><span class="pun">=</span><span class="pln"> enc</span><span class="pun">.</span><span class="pln">read</span><span class="pun">()</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="pun">-</span><span class="lit">4</span><span class="pun">;</span><span class="pln">
  236. </span><span class="com">//Make the screen update at least once when we enter this dialog</span><span class="pln">
  237. </span><span class="kwd">bool</span><span class="pln"> forceDraw </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
  238. </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">digitalRead</span><span class="pun">(</span><span class="pln">TIMER_BUT_PIN</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  239. </span><span class="kwd">int</span><span class="pln"> pos</span><span class="pun">,</span><span class="pln"> oldPos</span><span class="pun">;</span><span class="pln">
  240. pos </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">enc</span><span class="pun">.</span><span class="pln">read</span><span class="pun">()</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="pun">-</span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> offset </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">initial </span><span class="pun">-</span><span class="pln"> minOffset</span><span class="pun">);</span><span class="pln">
  241. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">pos </span><span class="pun">!=</span><span class="pln"> oldPos </span><span class="pun">||</span><span class="pln"> forceDraw</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  242. </span><span class="kwd">value</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">((</span><span class="pln">pos </span><span class="pun">+</span><span class="pln"> bound</span><span class="pun">)</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> bound</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> minOffset</span><span class="pun">;</span><span class="pln">
  243. screen</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">
  244. screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">before</span><span class="pun">);</span><span class="pln">
  245. sprintf</span><span class="pun">(</span><span class="pln">inputBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%2d"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">value</span><span class="pun">);</span><span class="pln">
  246. screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">inputBuffer</span><span class="pun">);</span><span class="pln">
  247. screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">after</span><span class="pun">);</span><span class="pln">
  248. oldPos </span><span class="pun">=</span><span class="pln"> pos</span><span class="pun">;</span><span class="pln">
  249. forceDraw </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
  250. </span><span class="pun">}</span><span class="pln">
  251. </span><span class="pun">}</span><span class="pln">
  252. </span><span class="com">//Wait for the user to release the button and debounce</span><span class="pln">
  253. </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">digitalRead</span><span class="pun">(</span><span class="pln">TIMER_BUT_PIN</span><span class="pun">));</span><span class="pln">
  254. delay</span><span class="pun">(</span><span class="lit">100</span><span class="pun">);</span><span class="pln">
  255. </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">value</span><span class="pun">;</span><span class="pln">
  256. </span><span class="pun">}</span><span class="pln">
  257. </span><span class="com">/* Draws the default clock face screen */</span><span class="pln">
  258. </span><span class="kwd">void</span><span class="pln"> drawHome</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  259. screen</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">
  260. screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
  261. </span><span class="typ">DateTime</span><span class="pln"> now </span><span class="pun">=</span><span class="pln"> DS3231M</span><span class="pun">.</span><span class="pln">now</span><span class="pun">();</span><span class="pln">
  262. </span><span class="kwd">int</span><span class="pln"> hr12 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">now</span><span class="pun">.</span><span class="pln">hour</span><span class="pun">()</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">12</span><span class="pun">);</span><span class="pln">
  263. hr12 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">hr12 </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="lit">12</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> hr12</span><span class="pun">;</span><span class="pln">
  264. sprintf</span><span class="pun">(</span><span class="pln">inputBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%d:%02d%c"</span><span class="pun">,</span><span class="pln"> hr12</span><span class="pun">,</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">minute</span><span class="pun">(),</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">hour</span><span class="pun">()</span><span class="pln"> </span><span class="pun">>=</span><span class="pln"> </span><span class="lit">12</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">'p'</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">'a'</span><span class="pun">);</span><span class="pln">
  265. screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">inputBuffer</span><span class="pun">);</span><span class="pln">
  266. screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">
  267. </span><span class="com">//Serial.println(weekDays[0]);</span><span class="pln">
  268. screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">weekDays</span><span class="pun">[</span><span class="pln">DS3231M</span><span class="pun">.</span><span class="pln">weekdayRead</span><span class="pun">()</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">7</span><span class="pun">]);</span><span class="pln">
  269. sprintf</span><span class="pun">(</span><span class="pln">inputBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">" %d/%d/%02d"</span><span class="pun">,</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">month</span><span class="pun">(),</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">day</span><span class="pun">(),</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">year</span><span class="pun">()</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">100</span><span class="pun">);</span><span class="pln">
  270. screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">inputBuffer</span><span class="pun">);</span><span class="pln">
  271. </span><span class="pun">}</span><span class="pln">
  272. </span><span class="com">/* Draws the timer screen for when an exercise interval is in progress */</span><span class="pln">
  273. </span><span class="kwd">void</span><span class="pln"> drawTimer</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  274. screen</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">
  275. screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
  276. screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Elapsed Time"</span><span class="pun">);</span><span class="pln">
  277. screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">
  278. </span><span class="kwd">long</span><span class="pln"> unixtime </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">DS3231M</span><span class="pun">.</span><span class="pln">now</span><span class="pun">()).</span><span class="pln">unixtime</span><span class="pun">();</span><span class="pln">
  279. </span><span class="kwd">long</span><span class="pln"> elapsed </span><span class="pun">=</span><span class="pln"> unixtime </span><span class="pun">-</span><span class="pln"> start</span><span class="pun">;</span><span class="pln">
  280. </span><span class="kwd">int</span><span class="pln"> seconds </span><span class="pun">=</span><span class="pln"> elapsed </span><span class="pun">%</span><span class="pln"> </span><span class="lit">60</span><span class="pun">;</span><span class="pln">
  281. elapsed </span><span class="pun">-=</span><span class="pln"> seconds</span><span class="pun">;</span><span class="pln">
  282. </span><span class="kwd">int</span><span class="pln"> minutes </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">elapsed </span><span class="pun">/</span><span class="pln"> </span><span class="lit">60</span><span class="pun">)</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">60</span><span class="pun">;</span><span class="pln">
  283. elapsed </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">elapsed </span><span class="pun">/</span><span class="pln"> </span><span class="lit">60</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> minutes</span><span class="pun">;</span><span class="pln">
  284. </span><span class="kwd">int</span><span class="pln"> hours </span><span class="pun">=</span><span class="pln"> elapsed </span><span class="pun">/</span><span class="pln"> </span><span class="lit">60</span><span class="pun">;</span><span class="pln">
  285. sprintf</span><span class="pun">(</span><span class="pln">inputBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">" %d:%02d:%02d"</span><span class="pun">,</span><span class="pln"> hours</span><span class="pun">,</span><span class="pln"> minutes</span><span class="pun">,</span><span class="pln"> seconds</span><span class="pun">);</span><span class="pln">
  286. screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">inputBuffer</span><span class="pun">);</span><span class="pln">
  287. </span><span class="pun">}</span><span class="pln">
  288. </span><span class="com">/* Draws the the 14 day bargraph screen (for during idle mode) */</span><span class="pln">
  289. </span><span class="kwd">void</span><span class="pln"> drawTwoWeekGraph</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> values</span><span class="pun">[])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  290. </span><span class="kwd">int</span><span class="pln"> weekDay </span><span class="pun">=</span><span class="pln"> DS3231M</span><span class="pun">.</span><span class="pln">weekdayRead</span><span class="pun">();</span><span class="pln">
  291. screen</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">
  292. initGraphChars</span><span class="pun">();</span><span class="pln">
  293. </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> </span><span class="lit">14</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  294. drawGraphBar</span><span class="pun">(</span><span class="pln">values</span><span class="pun">[</span><span class="lit">14</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">225</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">
  295. </span><span class="pun">}</span><span class="pln">
  296. screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln">
  297. </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> </span><span class="lit">15</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  298. screen</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="pln">weekLetters</span><span class="pun">[(</span><span class="pln">i </span><span class="pun">+</span><span class="pln"> weekDay</span><span class="pun">)</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">7</span><span class="pun">]);</span><span class="pln">
  299. </span><span class="pun">}</span><span class="pln">
  300. </span><span class="pun">}</span><span class="pln">
  301. </span><span class="com">/* Draws two horizantal graph bars, representing the total exercise time across the past two weeks */</span><span class="pln">
  302. </span><span class="kwd">void</span><span class="pln"> drawWeekCompare</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> w1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> w2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  303. screen</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">
  304. initBarChars</span><span class="pun">();</span><span class="pln">
  305. </span><span class="com">//See how much we've improved since last week</span><span class="pln">
  306. </span><span class="kwd">int</span><span class="pln"> percentChange </span><span class="pun">=</span><span class="pln"> </span><span class="pun">((</span><span class="pln">w2 </span><span class="pun">-</span><span class="pln"> w1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">100</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> w1</span><span class="pun">;</span><span class="pln">
  307. screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
  308. screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Last week"</span><span class="pun">);</span><span class="pln">
  309. drawHBar</span><span class="pun">(</span><span class="pln">w1 </span><span class="pun">/</span><span class="pln"> </span><span class="lit">300</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
  310. screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">
  311. screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="str">"This week ("</span><span class="pun">);</span><span class="pln">
  312. </span><span class="com">//Add a plus if we've gone up (negative added automatically)</span><span class="pln">
  313. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">percentChange </span><span class="pun">>=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  314. screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="str">"+"</span><span class="pun">);</span><span class="pln">
  315. </span><span class="pun">}</span><span class="pln">
  316. screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">percentChange</span><span class="pun">);</span><span class="pln">
  317. screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="str">"%)"</span><span class="pun">);</span><span class="pln">
  318. drawHBar</span><span class="pun">(</span><span class="pln">w2 </span><span class="pun">/</span><span class="pln"> </span><span class="lit">300</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln">
  319. </span><span class="pun">}</span><span class="pln">
  320. </span><span class="com">//Writes each of the horizantal progress bar chars into the LCD</span><span class="pln">
  321. </span><span class="kwd">void</span><span class="pln"> initBarChars</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  322. screen</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">
  323. </span><span class="com">//Start with an empty glyph for the bargraph char</span><span class="pln">
  324. </span><span class="kwd">byte</span><span class="pln"> hBar</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">};</span><span class="pln">
  325. </span><span class="com">//Loop through each bargraph level</span><span class="pln">
  326. </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  327. </span><span class="com">//Loop through each row of the character</span><span class="pln">
  328. </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> row </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> row </span><span class="pun"><</span><span class="pln"> </span><span class="lit">8</span><span class="pun">;</span><span class="pln"> row</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  329. </span><span class="com">//Add in a vertical bar (via bitwise OR)</span><span class="pln">
  330. hBar</span><span class="pun">[</span><span class="pln">row</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> hBar</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0B10000</span><span class="pln"> </span><span class="pun">>></span><span class="pln"> i</span><span class="pun">);</span><span class="pln">
  331. </span><span class="pun">}</span><span class="pln">
  332. screen</span><span class="pun">.</span><span class="pln">createChar</span><span class="pun">(</span><span class="pln">i</span><span class="pun">,</span><span class="pln"> hBar</span><span class="pun">);</span><span class="pln">
  333. </span><span class="pun">}</span><span class="pln">
  334. </span><span class="pun">}</span><span class="pln">
  335. </span><span class="com">/* Draws a horizantal graphbar x pixels wide on the given LCD row */</span><span class="pln">
  336. </span><span class="kwd">void</span><span class="pln"> drawHBar</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> row</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  337. screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> row</span><span class="pun">);</span><span class="pln">
  338. </span><span class="kwd">int</span><span class="pln"> offset </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  339. </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> offset </span><span class="pun">></span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  340. </span><span class="kwd">int</span><span class="pln"> blockChar </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">-</span><span class="pln"> offset</span><span class="pun">;</span><span class="pln">
  341. blockChar </span><span class="pun">=</span><span class="pln"> constrain</span><span class="pun">(</span><span class="pln">blockChar</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">);</span><span class="pln">
  342. screen</span><span class="pun">.</span><span class="pln">write</span><span class="pun">((</span><span class="pln">blockChar </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="lit">32</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> blockChar </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
  343. offset </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
  344. </span><span class="pun">}</span><span class="pln">
  345. </span><span class="pun">}</span><span class="pln">
  346. </span><span class="com">//Writes each of the bargraph level chars into the LCD</span><span class="pln">
  347. </span><span class="kwd">void</span><span class="pln"> initGraphChars</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  348. </span><span class="com">//Start with an empty glyph for the bargraph char</span><span class="pln">
  349. </span><span class="kwd">byte</span><span class="pln"> bar</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">};</span><span class="pln">
  350. </span><span class="com">//Loop through each bargraph level</span><span class="pln">
  351. </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> </span><span class="lit">8</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  352. </span><span class="com">//Set the lowest line to be all ones</span><span class="pln">
  353. bar</span><span class="pun">[</span><span class="lit">7</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0B11111</span><span class="pun">;</span><span class="pln">
  354. screen</span><span class="pun">.</span><span class="pln">createChar</span><span class="pun">(</span><span class="pln">i</span><span class="pun">,</span><span class="pln"> bar</span><span class="pun">);</span><span class="pln">
  355. </span><span class="pun">}</span><span class="pln">
  356. </span><span class="pun">}</span><span class="pln">
  357. </span><span class="com">/* Draws a vertical bar 'level' pixels high capped at a given height in char blocks
  358. at the given position (measured from the top of the bar space) */</span><span class="pln">
  359. </span><span class="kwd">void</span><span class="pln"> drawGraphBar</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> level</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> row</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> col</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> height</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  360. </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> y </span><span class="pun"><</span><span class="pln"> height</span><span class="pun">;</span><span class="pln"> y</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  361. </span><span class="kwd">int</span><span class="pln"> offset </span><span class="pun">=</span><span class="pln"> y </span><span class="pun">*</span><span class="pln"> </span><span class="lit">8</span><span class="pun">;</span><span class="pln">
  362. screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="pln">col</span><span class="pun">,</span><span class="pln"> row </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">height </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> y</span><span class="pun">);</span><span class="pln">
  363. </span><span class="kwd">int</span><span class="pln"> blockHeight </span><span class="pun">=</span><span class="pln"> level </span><span class="pun">-</span><span class="pln"> offset</span><span class="pun">;</span><span class="pln">
  364. </span><span class="com">//Limit the block height to 0-8</span><span class="pln">
  365. blockHeight </span><span class="pun">=</span><span class="pln"> constrain</span><span class="pun">(</span><span class="pln">blockHeight</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">);</span><span class="pln">
  366. screen</span><span class="pun">.</span><span class="pln">write</span><span class="pun">((</span><span class="pln">blockHeight </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="lit">32</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> blockHeight </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
  367. </span><span class="pun">}</span><span class="pln">
  368. </span><span class="pun">}</span><span class="pln">
  369. </span><span class="com">/* Take the sum of exercise time across an interval in our records */</span><span class="pln">
  370. </span><span class="kwd">int</span><span class="pln"> getTotalTime</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> start</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> finish</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  371. </span><span class="kwd">int</span><span class="pln"> </span><span class="kwd">out</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  372. </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> start</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> finish</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  373. </span><span class="kwd">out</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> pastTimes</span><span class="pun">[</span><span class="pln">i</span><span class="pun">];</span><span class="pln">
  374. </span><span class="pun">}</span><span class="pln">
  375. </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">out</span><span class="pun">;</span><span class="pln">
  376. </span><span class="pun">}</span><span class="pln">
  377. </span><span class="com">/* Starts and stops the exercise timer */</span><span class="pln">
  378. </span><span class="kwd">void</span><span class="pln"> timer</span><span class="pun">()</span><span class="pln">
  379. </span><span class="pun">{</span><span class="pln">
  380. </span><span class="kwd">long</span><span class="pln"> unixTime </span><span class="pun">=</span><span class="pln"> DS3231M</span><span class="pun">.</span><span class="pln">now</span><span class="pun">().</span><span class="pln">unixtime</span><span class="pun">();</span><span class="pln">
  381. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">timerOn</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  382. start </span><span class="pun">=</span><span class="pln"> unixTime</span><span class="pun">;</span><span class="pln">
  383. playSound</span><span class="pun">(</span><span class="pln">happySound</span><span class="pun">);</span><span class="pln">
  384. </span><span class="pun">}</span><span class="pln">
  385. </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  386. timeSeconds </span><span class="pun">=</span><span class="pln"> unixTime </span><span class="pun">-</span><span class="pln"> start</span><span class="pun">;</span><span class="pln">
  387. pastTimes</span><span class="pun">[</span><span class="lit">27</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> timeSeconds</span><span class="pun">;</span><span class="pln">
  388. </span><span class="com">//Set the screen up to show the bargraph</span><span class="pln">
  389. screenState </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
  390. updateTime </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">3000</span><span class="pun">;</span><span class="pln">
  391. </span><span class="pun">}</span><span class="pln">
  392. timerOn </span><span class="pun">=</span><span class="pln"> </span><span class="pun">!</span><span class="pln">timerOn</span><span class="pun">;</span><span class="pln">
  393. </span><span class="pun">}</span><span class="pln">
  394. </span><span class="com">/* Moves all recorded times over one day in memory (so day 27 is always the most recent) */</span><span class="pln">
  395. </span><span class="kwd">void</span><span class="pln"> shiftTimes</span><span class="pun">()</span><span class="pln">
  396. </span><span class="pun">{</span><span class="pln">
  397. </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> j </span><span class="pun"><</span><span class="pln"> </span><span class="lit">27</span><span class="pun">;</span><span class="pln"> j</span><span class="pun">++)</span><span class="pln">
  398. </span><span class="pun">{</span><span class="pln">
  399. pastTimes</span><span class="pun">[</span><span class="pln">j</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> pastTimes</span><span class="pun">[</span><span class="pln">j </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">];</span><span class="pln">
  400. </span><span class="pun">}</span><span class="pln">
  401. pastTimes</span><span class="pun">[</span><span class="lit">27</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  402. </span><span class="pun">}</span><span class="pln">
  403. </span><span class="com">/* Updates that need to be performed once each day */</span><span class="pln">
  404. </span><span class="kwd">void</span><span class="pln"> newDaySetup</span><span class="pun">()</span><span class="pln">
  405. </span><span class="pun">{</span><span class="pln">
  406. shiftTimes</span><span class="pun">();</span><span class="pln">
  407. timeSeconds </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  408. </span><span class="pun">}</span><span class="pln">
  409. </span><span class="com">/* Decide if a day has passed and we need to update things */</span><span class="pln">
  410. </span><span class="kwd">boolean</span><span class="pln"> isNewDay</span><span class="pun">()</span><span class="pln">
  411. </span><span class="pun">{</span><span class="pln">
  412. </span><span class="typ">DateTime</span><span class="pln"> now </span><span class="pun">=</span><span class="pln"> DS3231M</span><span class="pun">.</span><span class="pln">now</span><span class="pun">();</span><span class="pln">
  413. </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">now</span><span class="pun">.</span><span class="pln">hour</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">&&</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">minute</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">second</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
  414. </span><span class="pun">{</span><span class="pln">
  415. </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
  416. </span><span class="pun">}</span><span class="pln">
  417. </span><span class="kwd">else</span><span class="pln">
  418. </span><span class="pun">{</span><span class="pln">
  419. isMidnight </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
  420. </span><span class="pun">}</span><span class="pln">
  421. </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
  422. </span><span class="pun">}</span><span class="pln">
  423. </span><span class="com">/* Plays the given sound effect */</span><span class="pln">
  424. </span><span class="kwd">void</span><span class="pln"> playSound</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> noteArray</span><span class="pun">[])</span><span class="pln">
  425. </span><span class="pun">{</span><span class="pln">
  426. </span><span class="kwd">int</span><span class="pln"> noteLength </span><span class="pun">=</span><span class="pln"> noteArray</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">
  427. </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> thisNote </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> thisNote </span><span class="pun"><</span><span class="pln"> noteLength</span><span class="pun">;</span><span class="pln"> thisNote</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  428. </span><span class="kwd">int</span><span class="pln"> noteDuration </span><span class="pun">=</span><span class="pln"> noteArray</span><span class="pun">[</span><span class="lit">1</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> thisNote</span><span class="pun">];</span><span class="pln">
  429. </span><span class="kwd">int</span><span class="pln"> notePitch </span><span class="pun">=</span><span class="pln"> noteArray</span><span class="pun">[</span><span class="lit">2</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> noteLength </span><span class="pun">-</span><span class="pln"> noteLength </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> thisNote</span><span class="pun">];</span><span class="pln">
  430. </span><span class="kwd">int</span><span class="pln"> noteTime </span><span class="pun">=</span><span class="pln"> </span><span class="lit">300</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> noteDuration</span><span class="pun">;</span><span class="pln">
  431. tone</span><span class="pun">(</span><span class="pln">SPEAKER_PIN</span><span class="pun">,</span><span class="pln"> notePitch</span><span class="pun">,</span><span class="pln"> noteTime</span><span class="pun">);</span><span class="pln">
  432. </span><span class="kwd">int</span><span class="pln"> pauseBetweenNotes </span><span class="pun">=</span><span class="pln"> noteTime </span><span class="pun">*</span><span class="pln"> </span><span class="lit">1.30</span><span class="pun">;</span><span class="pln">
  433. delay</span><span class="pun">(</span><span class="pln">pauseBetweenNotes</span><span class="pun">);</span><span class="pln">
  434. noTone</span><span class="pun">(</span><span class="pln">SPEAKER_PIN</span><span class="pun">);</span><span class="pln">
  435. </span><span class="pun">}</span><span class="pln">
  436. </span><span class="pun">}</span><span class="pln">
  437. </span><span class="com">/* Update the LEDs to reflect which days we have and haven't logged times */</span><span class="pln">
  438. </span><span class="kwd">void</span><span class="pln"> updateLEDs</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  439. </span><span class="kwd">for</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> LED_CNT</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  440. digitalWrite</span><span class="pun">(</span><span class="pln">LED_BASE_PIN</span><span class="pun">,</span><span class="pln"> pastTimes</span><span class="pun">[</span><span class="lit">27</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">></span><span class="pln"> GOAL_TIME</span><span class="pun">);</span><span class="pln">
  441. </span><span class="pun">}</span><span class="pln">
  442. </span><span class="pun">}</span>
<span class="com">/*
 * Workout_Clock.ino
 * 
 * Exercise Reminder Clock
 * Karen Abruzzo, Justin Kiefel, George Ralph
 * 
 * This code runs a clock, which can be used to track the duration of
 * exercise intervals with stopwatch-like functionality whenever TIMER_BUT_PIN
 * is pressed. The clock also tracks exercise history over a 2 week period, 
 * and reminds the user through audio tones to exercise whenever they are 
 * detected by the motion sensor. (Though this feature can be disabled)
 * 
 * Inputs
 *    0   -   Motion Sensor
 *    2   -   Rotary Encoder Clock Pin
 *    3   -   Rotary Encoder Data Pin
 *    4   -   Rotary Encoder Button
 *    5   -   Power/Mute Switch
 * 
 * Outputs
 *    6     - Speaker Pin
 *    7..13 - Bargraph LEDs
 *    
 * Outputs
 * 
 * NOTE: This project must be compiled with compiler warnings disabled due to 
 *       aspects of the libraries we use, which are beyond our control.
 */</span><span class="pln">

</span><span class="com">#include</span><span class="pln"> </span><span class="str"><Encoder.h></span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str"><Wire.h></span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str"><DS3231M.h></span><span class="pln"> </span><span class="com">//library for the rtc</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str"><LiquidCrystal_I2C.h></span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">"pitches.h"</span><span class="pln">

</span><span class="com">/* Create an LCD display object called "screen" with I2C address 0x27
   which is 20 columns wide and 4 rows tall. You can use any name you'd like. */</span><span class="pln">
</span><span class="typ">LiquidCrystal_I2C</span><span class="pln"> screen</span><span class="pun">(</span><span class="lit">0x27</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">);</span><span class="pln">
DS3231M_Class DS3231M</span><span class="pun">;</span><span class="pln">

</span><span class="com">//Make buffer size the size of the screen area, just to be safe</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">uint8_t</span><span class="pln">  SPRINTF_BUFFER_SIZE </span><span class="pun">=</span><span class="pln"> </span><span class="lit">80</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">char</span><span class="pln"> inputBuffer</span><span class="pun">[</span><span class="pln">SPRINTF_BUFFER_SIZE</span><span class="pun">];</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">uint32_t</span><span class="pln"> SERIAL_SPEED </span><span class="pun">=</span><span class="pln"> </span><span class="lit">115200</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> MOTION_PIN         </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> ENC_CLK_PIN        </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> ENC_DT_PIN         </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> TIMER_BUT_PIN      </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> POWER_SWITCH       </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> SPEAKER_PIN        </span><span class="pun">=</span><span class="pln"> </span><span class="lit">6</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> LED_BASE_PIN       </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> LED_CNT </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pun">;</span><span class="pln">

</span><span class="com">//Goal time is 40 minutes</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> GOAL_TIME </span><span class="pun">=</span><span class="pln"> </span><span class="lit">60</span><span class="pun">*</span><span class="lit">40</span><span class="pun">;</span><span class="pln">

</span><span class="typ">Encoder</span><span class="pln"> enc</span><span class="pun">(</span><span class="pln">ENC_CLK_PIN</span><span class="pun">,</span><span class="pln"> ENC_DT_PIN</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> weekLetters</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="str">'S'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'M'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'T'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'W'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'H'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'F'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'S'</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> weekDays</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="str">"Sunday"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Monday"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Tuesday"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Wednesday"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Thursday"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Friday"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Saturday"</span><span class="pun">};</span><span class="pln">


</span><span class="com">// 2 = half note, 4 = quarter note, ect.</span><span class="pln">

</span><span class="kwd">int</span><span class="pln"> openSound</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> NOTE_B3</span><span class="pun">,</span><span class="pln"> NOTE_B4</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">int</span><span class="pln"> workoutSound</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16</span><span class="pun">,</span><span class="pln"> NOTE_B3</span><span class="pun">,</span><span class="pln"> NOTE_B5</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">int</span><span class="pln"> clockSound</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> NOTE_A5</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">int</span><span class="pln"> sadSound</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> NOTE_F3</span><span class="pun">,</span><span class="pln"> NOTE_C3</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">int</span><span class="pln"> happySound</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">{</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> NOTE_C4</span><span class="pun">,</span><span class="pln"> NOTE_E4</span><span class="pun">,</span><span class="pln"> NOTE_G4</span><span class="pun">,</span><span class="pln"> NOTE_C5</span><span class="pun">};</span><span class="pln">


</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> start</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> timerOn </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">int</span><span class="pln"> pastTimes</span><span class="pun">[</span><span class="lit">28</span><span class="pun">];</span><span class="pln">
</span><span class="kwd">int</span><span class="pln"> timeSeconds</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">boolean</span><span class="pln"> isMidnight </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">


</span><span class="kwd">long</span><span class="pln"> lastPing </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">long</span><span class="pln"> pingTimeout </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3600</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">bool</span><span class="pln"> advancePast </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> timerPast </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">long</span><span class="pln"> updateTime</span><span class="pun">,</span><span class="pln"> buttonDownTime</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">int</span><span class="pln"> screenState </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">bool</span><span class="pln"> pastPowerState </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> powerState </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> setup</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// Initialize pins</span><span class="pln">
  pinMode</span><span class="pun">(</span><span class="pln">TIMER_BUT_PIN</span><span class="pun">,</span><span class="pln"> INPUT_PULLUP</span><span class="pun">);</span><span class="pln">
  pinMode</span><span class="pun">(</span><span class="pln">POWER_SWITCH</span><span class="pun">,</span><span class="pln"> INPUT_PULLUP</span><span class="pun">);</span><span class="pln">
  pinMode</span><span class="pun">(</span><span class="pln">SPEAKER_PIN</span><span class="pun">,</span><span class="pln"> OUTPUT</span><span class="pun">);</span><span class="pln">
  pinMode</span><span class="pun">(</span><span class="pln">MOTION_PIN</span><span class="pun">,</span><span class="pln"> INPUT</span><span class="pun">);</span><span class="pln">

  digitalWrite</span><span class="pun">(</span><span class="pln">SPEAKER_PIN</span><span class="pun">,</span><span class="pln"> LOW</span><span class="pun">);</span><span class="pln">
  
  </span><span class="com">//Initialize the LED pins as a consecutive block of pins</span><span class="pln">
  </span><span class="kwd">for</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> LED_CNT</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    pinMode</span><span class="pun">(</span><span class="pln">LED_BASE_PIN </span><span class="pun">+</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> OUTPUT</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  
  </span><span class="com">//setup pins</span><span class="pln">
  </span><span class="com">//Serial.begin(SERIAL_SPEED);</span><span class="pln">

  </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">DS3231M</span><span class="pun">.</span><span class="kwd">begin</span><span class="pun">())</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    </span><span class="com">//Serial.println(F("Unable to find DS3231MM. Checking again in 3s."));</span><span class="pln">
    delay</span><span class="pun">(</span><span class="lit">3000</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="com">// initialize the screen (only need to do this once)</span><span class="pln">
  screen</span><span class="pun">.</span><span class="pln">init</span><span class="pun">();</span><span class="pln">
  screen</span><span class="pun">.</span><span class="pln">backlight</span><span class="pun">();</span><span class="pln">
  
  powerState </span><span class="pun">=</span><span class="pln"> </span><span class="pun">!</span><span class="pln">digitalRead</span><span class="pun">(</span><span class="pln">POWER_SWITCH</span><span class="pun">);</span><span class="pln">
  pastPowerState </span><span class="pun">=</span><span class="pln"> powerState</span><span class="pun">;</span><span class="pln">
  
  </span><span class="typ">DateTime</span><span class="pln"> now </span><span class="pun">=</span><span class="pln"> DS3231M</span><span class="pun">.</span><span class="pln">now</span><span class="pun">();</span><span class="pln">
  lastPing </span><span class="pun">=</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">unixtime</span><span class="pun">();</span><span class="pln">

  updateTime </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">();</span><span class="pln">

  </span><span class="com">//setTime();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> loop</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">bool</span><span class="pln"> timerState </span><span class="pun">=</span><span class="pln"> </span><span class="pun">!</span><span class="pln">digitalRead</span><span class="pun">(</span><span class="pln">TIMER_BUT_PIN</span><span class="pun">);</span><span class="pln">
  </span><span class="kwd">bool</span><span class="pln"> powerState </span><span class="pun">=</span><span class="pln"> </span><span class="pun">!</span><span class="pln">digitalRead</span><span class="pun">(</span><span class="pln">POWER_SWITCH</span><span class="pun">);</span><span class="pln">

  </span><span class="com">//On button down</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">timerState </span><span class="pun">&&</span><span class="pln"> </span><span class="pun">!</span><span class="pln">timerPast</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    buttonDownTime </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="com">//On button up</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">timerState </span><span class="pun">&&</span><span class="pln"> timerPast</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">//If the button has been down for more than a second</span><span class="pln">
    </span><span class="com">//Enter settings dialog</span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">buttonDownTime </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1000</span><span class="pln"> </span><span class="pun"><=</span><span class="pln"> millis</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      setTime</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln">
    </span><span class="com">//Otherwise, start the timer</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
      timer</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    
    updateTime </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">3000</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="com">//In timer mode, draw the elapsed time so far</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">timerOn</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">//But only, once a second</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">((</span><span class="pln">updateTime </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">)</span><span class="pln"> </span><span class="pun"><=</span><span class="pln"> millis</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      drawTimer</span><span class="pun">();</span><span class="pln">
      updateTime </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="kwd">else</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">powerState</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="com">//Cycle the screen every 3 seconds when power is on</span><span class="pln">
      </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">((</span><span class="pln">updateTime </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3000</span><span class="pun">)</span><span class="pln"> </span><span class="pun"><=</span><span class="pln"> millis</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">screenState</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
          </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            drawHome</span><span class="pun">();</span><span class="pln">
            </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
            
          </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            drawWeekCompare</span><span class="pun">(</span><span class="pln">getTotalTime</span><span class="pun">(</span><span class="lit">14</span><span class="pun">,</span><span class="pln"> </span><span class="lit">21</span><span class="pun">),</span><span class="pln"> getTotalTime</span><span class="pun">(</span><span class="lit">21</span><span class="pun">,</span><span class="pln"> </span><span class="lit">28</span><span class="pun">));</span><span class="pln">
            </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
            
          </span><span class="kwd">case</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
            drawTwoWeekGraph</span><span class="pun">(</span><span class="pln">pastTimes</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        
        updateTime </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">();</span><span class="pln">
        screenState </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">screenState </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">  
      </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
      </span><span class="com">//Update the clock every few seconds when power is off</span><span class="pln">
      </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">((</span><span class="pln">updateTime </span><span class="pun">+</span><span class="pln"> </span><span class="lit">5000</span><span class="pun">)</span><span class="pln"> </span><span class="pun"><=</span><span class="pln"> millis</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        drawHome</span><span class="pun">();</span><span class="pln">
        updateTime </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">();</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">//If no time is logged for today (and device is on)</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">pastTimes</span><span class="pun">[</span><span class="lit">27</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">&&</span><span class="pln"> powerState</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="com">//If the motion sensor detects motion</span><span class="pln">
      </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">digitalRead</span><span class="pun">(</span><span class="pln">MOTION_PIN</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">//If it's been a while since we last pinged</span><span class="pln">
        </span><span class="typ">DateTime</span><span class="pln"> now </span><span class="pun">=</span><span class="pln"> DS3231M</span><span class="pun">.</span><span class="pln">now</span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">now</span><span class="pun">.</span><span class="pln">unixtime</span><span class="pun">()</span><span class="pln"> </span><span class="pun">>=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">lastPing </span><span class="pun">+</span><span class="pln"> pingTimeout</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
          </span><span class="com">//Ping the user</span><span class="pln">
          playSound</span><span class="pun">(</span><span class="pln">sadSound</span><span class="pun">);</span><span class="pln">
          lastPing </span><span class="pun">=</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">unixtime</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">isNewDay</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&&</span><span class="pln"> </span><span class="pun">!</span><span class="pln">isMidnight</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    newDaySetup</span><span class="pun">();</span><span class="pln">
    isMidnight </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  updateLEDs</span><span class="pun">();</span><span class="pln">
  
  </span><span class="com">//Turn the screen on/off if the power switch is flipped</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">powerState </span><span class="pun">!=</span><span class="pln"> pastPowerState</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">powerState</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      screen</span><span class="pun">.</span><span class="pln">backlight</span><span class="pun">();</span><span class="pln">
      updateTime </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      screen</span><span class="pun">.</span><span class="pln">noBacklight</span><span class="pun">();</span><span class="pln">
      screenState </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
      drawHome</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">

  pastPowerState </span><span class="pun">=</span><span class="pln"> powerState</span><span class="pun">;</span><span class="pln">
  timerPast </span><span class="pun">=</span><span class="pln"> timerState</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">/* The time-setting dialog menu */</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> setTime</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  screen</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">

  </span><span class="com">//Grab the current time</span><span class="pln">
  </span><span class="typ">DateTime</span><span class="pln"> now </span><span class="pun">=</span><span class="pln"> DS3231M</span><span class="pun">.</span><span class="pln">now</span><span class="pun">();</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> hour </span><span class="pun">=</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">hour</span><span class="pun">();</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> minute </span><span class="pun">=</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">minute</span><span class="pun">();</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> day </span><span class="pun">=</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">day</span><span class="pun">();</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> month </span><span class="pun">=</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">month</span><span class="pun">();</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> year </span><span class="pun">=</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">year</span><span class="pun">();</span><span class="pln">
  
  </span><span class="com">//Initialize buffers to print before and after the number we choose</span><span class="pln">
  </span><span class="kwd">char</span><span class="pln"> beforeBuffer</span><span class="pun">[</span><span class="pln">SPRINTF_BUFFER_SIZE</span><span class="pun">];</span><span class="pln">
  </span><span class="kwd">char</span><span class="pln"> afterBuffer</span><span class="pun">[</span><span class="pln">SPRINTF_BUFFER_SIZE</span><span class="pun">];</span><span class="pln">

  </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> header </span><span class="pun">=</span><span class="pln"> </span><span class="str">"      Set Time      "</span><span class="pun">;</span><span class="pln">

  </span><span class="com">//For each time, format the string around it with the previously set time</span><span class="pln">
  sprintf</span><span class="pun">(</span><span class="pln">beforeBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%s ("</span><span class="pun">,</span><span class="pln"> header</span><span class="pun">);</span><span class="pln">
  sprintf</span><span class="pun">(</span><span class="pln">afterBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">"):%02d %d/%02d/%04d"</span><span class="pun">,</span><span class="pln"> minute</span><span class="pun">,</span><span class="pln"> month</span><span class="pun">,</span><span class="pln"> day</span><span class="pun">,</span><span class="pln"> year</span><span class="pun">);</span><span class="pln">
  hour   </span><span class="pun">=</span><span class="pln"> getNumInput</span><span class="pun">(</span><span class="lit">24</span><span class="pun">,</span><span class="pln">    beforeBuffer</span><span class="pun">,</span><span class="pln"> afterBuffer</span><span class="pun">,</span><span class="pln">   hour</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
  
  sprintf</span><span class="pun">(</span><span class="pln">beforeBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%s %2d:("</span><span class="pun">,</span><span class="pln"> header</span><span class="pun">,</span><span class="pln"> hour</span><span class="pun">);</span><span class="pln">
  sprintf</span><span class="pun">(</span><span class="pln">afterBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">") %d/%02d/%04d"</span><span class="pun">,</span><span class="pln"> month</span><span class="pun">,</span><span class="pln"> day</span><span class="pun">,</span><span class="pln"> year</span><span class="pun">);</span><span class="pln">
  minute </span><span class="pun">=</span><span class="pln"> getNumInput</span><span class="pun">(</span><span class="lit">60</span><span class="pun">,</span><span class="pln">    beforeBuffer</span><span class="pun">,</span><span class="pln"> afterBuffer</span><span class="pun">,</span><span class="pln"> minute</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">

  sprintf</span><span class="pun">(</span><span class="pln">beforeBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%s %2d:%02d ("</span><span class="pun">,</span><span class="pln"> header</span><span class="pun">,</span><span class="pln"> hour</span><span class="pun">,</span><span class="pln"> minute</span><span class="pun">);</span><span class="pln">
  sprintf</span><span class="pun">(</span><span class="pln">afterBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">")/%02d/%04d"</span><span class="pun">,</span><span class="pln"> day</span><span class="pun">,</span><span class="pln"> year</span><span class="pun">);</span><span class="pln">
  month  </span><span class="pun">=</span><span class="pln"> getNumInput</span><span class="pun">(</span><span class="lit">12</span><span class="pun">,</span><span class="pln">    beforeBuffer</span><span class="pun">,</span><span class="pln"> afterBuffer</span><span class="pun">,</span><span class="pln">  month</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">

  sprintf</span><span class="pun">(</span><span class="pln">beforeBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%s %2d:%02d %2d/("</span><span class="pun">,</span><span class="pln"> header</span><span class="pun">,</span><span class="pln"> hour</span><span class="pun">,</span><span class="pln"> minute</span><span class="pun">,</span><span class="pln"> month</span><span class="pun">);</span><span class="pln">
  sprintf</span><span class="pun">(</span><span class="pln">afterBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">")/%04d"</span><span class="pun">,</span><span class="pln"> year</span><span class="pun">);</span><span class="pln">
  day    </span><span class="pun">=</span><span class="pln"> getNumInput</span><span class="pun">(</span><span class="lit">31</span><span class="pun">,</span><span class="pln">    beforeBuffer</span><span class="pun">,</span><span class="pln"> afterBuffer</span><span class="pun">,</span><span class="pln">    day</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
  
  sprintf</span><span class="pun">(</span><span class="pln">beforeBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%s %2d:%02d %2d/%02d/("</span><span class="pun">,</span><span class="pln"> header</span><span class="pun">,</span><span class="pln"> hour</span><span class="pun">,</span><span class="pln"> minute</span><span class="pun">,</span><span class="pln"> month</span><span class="pun">,</span><span class="pln"> day</span><span class="pun">);</span><span class="pln">
  sprintf</span><span class="pun">(</span><span class="pln">afterBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">")"</span><span class="pun">);</span><span class="pln">
  year   </span><span class="pun">=</span><span class="pln"> getNumInput</span><span class="pun">(</span><span class="lit">10000</span><span class="pun">,</span><span class="pln"> beforeBuffer</span><span class="pun">,</span><span class="pln"> afterBuffer</span><span class="pun">,</span><span class="pln">   year</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">

  </span><span class="typ">DateTime</span><span class="pln"> newTime </span><span class="pun">=</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">(</span><span class="pln">year</span><span class="pun">,</span><span class="pln"> month</span><span class="pun">,</span><span class="pln"> day</span><span class="pun">,</span><span class="pln"> hour</span><span class="pun">,</span><span class="pln"> minute</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
  DS3231M</span><span class="pun">.</span><span class="pln">adjust</span><span class="pun">(</span><span class="pln">newTime</span><span class="pun">);</span><span class="pln">

  </span><span class="com">//Make sure we show the clock screen after this</span><span class="pln">
  screenState </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">/* Creates a number input dialog, with strings before and after the number 
   An initial value can be specified, 
   Input is modular about bound (ie 60 for values 0-59)
   The bound range can be offset via minOffset (ie 1 for 1-60 in the above example) */</span><span class="pln">
</span><span class="kwd">int</span><span class="pln"> getNumInput</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> bound</span><span class="pun">,</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> before</span><span class="pun">,</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> after</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> initial</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> minOffset</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> </span><span class="kwd">value</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> offset </span><span class="pun">=</span><span class="pln"> enc</span><span class="pun">.</span><span class="pln">read</span><span class="pun">()</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="pun">-</span><span class="lit">4</span><span class="pun">;</span><span class="pln">
  </span><span class="com">//Make the screen update at least once when we enter this dialog</span><span class="pln">
  </span><span class="kwd">bool</span><span class="pln"> forceDraw </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">

  </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">digitalRead</span><span class="pun">(</span><span class="pln">TIMER_BUT_PIN</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">int</span><span class="pln"> pos</span><span class="pun">,</span><span class="pln"> oldPos</span><span class="pun">;</span><span class="pln">
    pos </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">enc</span><span class="pun">.</span><span class="pln">read</span><span class="pun">()</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="pun">-</span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> offset </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">initial </span><span class="pun">-</span><span class="pln"> minOffset</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">pos </span><span class="pun">!=</span><span class="pln"> oldPos </span><span class="pun">||</span><span class="pln"> forceDraw</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="kwd">value</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">((</span><span class="pln">pos </span><span class="pun">+</span><span class="pln"> bound</span><span class="pun">)</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> bound</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> minOffset</span><span class="pun">;</span><span class="pln">
      screen</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">
      screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">before</span><span class="pun">);</span><span class="pln">

      sprintf</span><span class="pun">(</span><span class="pln">inputBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%2d"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">value</span><span class="pun">);</span><span class="pln">
      
      screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">inputBuffer</span><span class="pun">);</span><span class="pln">
      screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">after</span><span class="pun">);</span><span class="pln">
      oldPos </span><span class="pun">=</span><span class="pln"> pos</span><span class="pun">;</span><span class="pln">
      forceDraw </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="com">//Wait for the user to release the button and debounce</span><span class="pln">
  </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">digitalRead</span><span class="pun">(</span><span class="pln">TIMER_BUT_PIN</span><span class="pun">));</span><span class="pln">
  delay</span><span class="pun">(</span><span class="lit">100</span><span class="pun">);</span><span class="pln">

  </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">value</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">/* Draws the default clock face screen */</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> drawHome</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  screen</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">

  screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">DateTime</span><span class="pln"> now </span><span class="pun">=</span><span class="pln"> DS3231M</span><span class="pun">.</span><span class="pln">now</span><span class="pun">();</span><span class="pln">

  </span><span class="kwd">int</span><span class="pln"> hr12 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">now</span><span class="pun">.</span><span class="pln">hour</span><span class="pun">()</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">12</span><span class="pun">);</span><span class="pln">
  hr12 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">hr12 </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="lit">12</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> hr12</span><span class="pun">;</span><span class="pln">

  sprintf</span><span class="pun">(</span><span class="pln">inputBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%d:%02d%c"</span><span class="pun">,</span><span class="pln"> hr12</span><span class="pun">,</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">minute</span><span class="pun">(),</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">hour</span><span class="pun">()</span><span class="pln"> </span><span class="pun">>=</span><span class="pln"> </span><span class="lit">12</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">'p'</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">'a'</span><span class="pun">);</span><span class="pln">
  screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">inputBuffer</span><span class="pun">);</span><span class="pln">
  screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">

  </span><span class="com">//Serial.println(weekDays[0]);</span><span class="pln">

  screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">weekDays</span><span class="pun">[</span><span class="pln">DS3231M</span><span class="pun">.</span><span class="pln">weekdayRead</span><span class="pun">()</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">7</span><span class="pun">]);</span><span class="pln">
  sprintf</span><span class="pun">(</span><span class="pln">inputBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">" %d/%d/%02d"</span><span class="pun">,</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">month</span><span class="pun">(),</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">day</span><span class="pun">(),</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">year</span><span class="pun">()</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">100</span><span class="pun">);</span><span class="pln">
  screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">inputBuffer</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">/* Draws the timer screen for when an exercise interval is in progress */</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> drawTimer</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  screen</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">
  screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
  screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Elapsed Time"</span><span class="pun">);</span><span class="pln">
  
  screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">

  </span><span class="kwd">long</span><span class="pln"> unixtime </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">DS3231M</span><span class="pun">.</span><span class="pln">now</span><span class="pun">()).</span><span class="pln">unixtime</span><span class="pun">();</span><span class="pln">
  </span><span class="kwd">long</span><span class="pln"> elapsed </span><span class="pun">=</span><span class="pln"> unixtime </span><span class="pun">-</span><span class="pln"> start</span><span class="pun">;</span><span class="pln">

  </span><span class="kwd">int</span><span class="pln"> seconds </span><span class="pun">=</span><span class="pln"> elapsed </span><span class="pun">%</span><span class="pln"> </span><span class="lit">60</span><span class="pun">;</span><span class="pln">
  elapsed </span><span class="pun">-=</span><span class="pln"> seconds</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> minutes </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">elapsed </span><span class="pun">/</span><span class="pln"> </span><span class="lit">60</span><span class="pun">)</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">60</span><span class="pun">;</span><span class="pln">
  elapsed </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">elapsed </span><span class="pun">/</span><span class="pln"> </span><span class="lit">60</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> minutes</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> hours </span><span class="pun">=</span><span class="pln"> elapsed </span><span class="pun">/</span><span class="pln"> </span><span class="lit">60</span><span class="pun">;</span><span class="pln">

  sprintf</span><span class="pun">(</span><span class="pln">inputBuffer</span><span class="pun">,</span><span class="pln"> </span><span class="str">" %d:%02d:%02d"</span><span class="pun">,</span><span class="pln"> hours</span><span class="pun">,</span><span class="pln"> minutes</span><span class="pun">,</span><span class="pln"> seconds</span><span class="pun">);</span><span class="pln">
  screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">inputBuffer</span><span class="pun">);</span><span class="pln">

</span><span class="pun">}</span><span class="pln">

</span><span class="com">/* Draws the the 14 day bargraph screen (for during idle mode) */</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> drawTwoWeekGraph</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> values</span><span class="pun">[])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> weekDay </span><span class="pun">=</span><span class="pln"> DS3231M</span><span class="pun">.</span><span class="pln">weekdayRead</span><span class="pun">();</span><span class="pln">

  screen</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">
  initGraphChars</span><span class="pun">();</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> </span><span class="lit">14</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    drawGraphBar</span><span class="pun">(</span><span class="pln">values</span><span class="pun">[</span><span class="lit">14</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">225</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> </span><span class="lit">15</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    screen</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="pln">weekLetters</span><span class="pun">[(</span><span class="pln">i </span><span class="pun">+</span><span class="pln"> weekDay</span><span class="pun">)</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">7</span><span class="pun">]);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">/* Draws two horizantal graph bars, representing the total exercise time across the past two weeks */</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> drawWeekCompare</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> w1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> w2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  screen</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">
  initBarChars</span><span class="pun">();</span><span class="pln">

  </span><span class="com">//See how much we've improved since last week</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> percentChange </span><span class="pun">=</span><span class="pln"> </span><span class="pun">((</span><span class="pln">w2 </span><span class="pun">-</span><span class="pln"> w1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">100</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> w1</span><span class="pun">;</span><span class="pln">

  screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
  screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Last week"</span><span class="pun">);</span><span class="pln">
  drawHBar</span><span class="pun">(</span><span class="pln">w1 </span><span class="pun">/</span><span class="pln"> </span><span class="lit">300</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">

  screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">
  screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="str">"This week ("</span><span class="pun">);</span><span class="pln">

  </span><span class="com">//Add a plus if we've gone up (negative added automatically)</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">percentChange </span><span class="pun">>=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="str">"+"</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">percentChange</span><span class="pun">);</span><span class="pln">
  screen</span><span class="pun">.</span><span class="kwd">print</span><span class="pun">(</span><span class="str">"%)"</span><span class="pun">);</span><span class="pln">

  drawHBar</span><span class="pun">(</span><span class="pln">w2 </span><span class="pun">/</span><span class="pln"> </span><span class="lit">300</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">//Writes each of the horizantal progress bar chars into the LCD</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> initBarChars</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  screen</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span><span class="pln">
  </span><span class="com">//Start with an empty glyph for the bargraph char</span><span class="pln">
  </span><span class="kwd">byte</span><span class="pln"> hBar</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">};</span><span class="pln">

  </span><span class="com">//Loop through each bargraph level</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">//Loop through each row of the character</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> row </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> row </span><span class="pun"><</span><span class="pln"> </span><span class="lit">8</span><span class="pun">;</span><span class="pln"> row</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="com">//Add in a vertical bar (via bitwise OR)</span><span class="pln">
      hBar</span><span class="pun">[</span><span class="pln">row</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> hBar</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0B10000</span><span class="pln"> </span><span class="pun">>></span><span class="pln"> i</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    screen</span><span class="pun">.</span><span class="pln">createChar</span><span class="pun">(</span><span class="pln">i</span><span class="pun">,</span><span class="pln"> hBar</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">


</span><span class="com">/* Draws a horizantal graphbar x pixels wide on the given LCD row */</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> drawHBar</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> row</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> row</span><span class="pun">);</span><span class="pln">

  </span><span class="kwd">int</span><span class="pln"> offset </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> offset </span><span class="pun">></span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">int</span><span class="pln"> blockChar </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">-</span><span class="pln"> offset</span><span class="pun">;</span><span class="pln">
    blockChar </span><span class="pun">=</span><span class="pln"> constrain</span><span class="pun">(</span><span class="pln">blockChar</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">);</span><span class="pln">

    screen</span><span class="pun">.</span><span class="pln">write</span><span class="pun">((</span><span class="pln">blockChar </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="lit">32</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> blockChar </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">

    offset </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">//Writes each of the bargraph level chars into the LCD</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> initGraphChars</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">//Start with an empty glyph for the bargraph char</span><span class="pln">
  </span><span class="kwd">byte</span><span class="pln"> bar</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">};</span><span class="pln">

  </span><span class="com">//Loop through each bargraph level</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> </span><span class="lit">8</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">//Set the lowest line to be all ones</span><span class="pln">
    bar</span><span class="pun">[</span><span class="lit">7</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0B11111</span><span class="pun">;</span><span class="pln">
    screen</span><span class="pun">.</span><span class="pln">createChar</span><span class="pun">(</span><span class="pln">i</span><span class="pun">,</span><span class="pln"> bar</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">/* Draws a vertical bar 'level' pixels high capped at a given height in char blocks
   at the given position (measured from the top of the bar space) */</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> drawGraphBar</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> level</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> row</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> col</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> height</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> y </span><span class="pun"><</span><span class="pln"> height</span><span class="pun">;</span><span class="pln"> y</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">int</span><span class="pln"> offset </span><span class="pun">=</span><span class="pln"> y </span><span class="pun">*</span><span class="pln"> </span><span class="lit">8</span><span class="pun">;</span><span class="pln">
    screen</span><span class="pun">.</span><span class="pln">setCursor</span><span class="pun">(</span><span class="pln">col</span><span class="pun">,</span><span class="pln"> row </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">height </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> y</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">int</span><span class="pln"> blockHeight </span><span class="pun">=</span><span class="pln"> level </span><span class="pun">-</span><span class="pln"> offset</span><span class="pun">;</span><span class="pln">

    </span><span class="com">//Limit the block height to 0-8</span><span class="pln">
    blockHeight </span><span class="pun">=</span><span class="pln"> constrain</span><span class="pun">(</span><span class="pln">blockHeight</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">);</span><span class="pln">

    screen</span><span class="pun">.</span><span class="pln">write</span><span class="pun">((</span><span class="pln">blockHeight </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="lit">32</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> blockHeight </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">/* Take the sum of exercise time across an interval in our records */</span><span class="pln">
</span><span class="kwd">int</span><span class="pln"> getTotalTime</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> start</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> finish</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> </span><span class="kwd">out</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">

  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> start</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> finish</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">out</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> pastTimes</span><span class="pun">[</span><span class="pln">i</span><span class="pun">];</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">out</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">/* Starts and stops the exercise timer */</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> timer</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">long</span><span class="pln"> unixTime </span><span class="pun">=</span><span class="pln"> DS3231M</span><span class="pun">.</span><span class="pln">now</span><span class="pun">().</span><span class="pln">unixtime</span><span class="pun">();</span><span class="pln">

  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">timerOn</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    start </span><span class="pun">=</span><span class="pln"> unixTime</span><span class="pun">;</span><span class="pln">
    playSound</span><span class="pun">(</span><span class="pln">happySound</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    timeSeconds </span><span class="pun">=</span><span class="pln"> unixTime </span><span class="pun">-</span><span class="pln"> start</span><span class="pun">;</span><span class="pln">

    pastTimes</span><span class="pun">[</span><span class="lit">27</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> timeSeconds</span><span class="pun">;</span><span class="pln">
    
    </span><span class="com">//Set the screen up to show the bargraph</span><span class="pln">
    screenState </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
    updateTime </span><span class="pun">=</span><span class="pln"> millis</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">3000</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  timerOn </span><span class="pun">=</span><span class="pln"> </span><span class="pun">!</span><span class="pln">timerOn</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">/* Moves all recorded times over one day in memory (so day 27 is always the most recent) */</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> shiftTimes</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> j </span><span class="pun"><</span><span class="pln"> </span><span class="lit">27</span><span class="pun">;</span><span class="pln"> j</span><span class="pun">++)</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    pastTimes</span><span class="pun">[</span><span class="pln">j</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> pastTimes</span><span class="pun">[</span><span class="pln">j </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">];</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  pastTimes</span><span class="pun">[</span><span class="lit">27</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">/* Updates that need to be performed once each day */</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> newDaySetup</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
  shiftTimes</span><span class="pun">();</span><span class="pln">
  timeSeconds </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">/* Decide if a day has passed and we need to update things */</span><span class="pln">
</span><span class="kwd">boolean</span><span class="pln"> isNewDay</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
  </span><span class="typ">DateTime</span><span class="pln"> now </span><span class="pun">=</span><span class="pln"> DS3231M</span><span class="pun">.</span><span class="pln">now</span><span class="pun">();</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">now</span><span class="pun">.</span><span class="pln">hour</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">&&</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">minute</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> now</span><span class="pun">.</span><span class="pln">second</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">
  </span><span class="kwd">else</span><span class="pln">
  </span><span class="pun">{</span><span class="pln">
    isMidnight </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">/* Plays the given sound effect */</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> playSound</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> noteArray</span><span class="pun">[])</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> noteLength </span><span class="pun">=</span><span class="pln"> noteArray</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> thisNote </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> thisNote </span><span class="pun"><</span><span class="pln"> noteLength</span><span class="pun">;</span><span class="pln"> thisNote</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">int</span><span class="pln"> noteDuration </span><span class="pun">=</span><span class="pln"> noteArray</span><span class="pun">[</span><span class="lit">1</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> thisNote</span><span class="pun">];</span><span class="pln">
    </span><span class="kwd">int</span><span class="pln"> notePitch </span><span class="pun">=</span><span class="pln"> noteArray</span><span class="pun">[</span><span class="lit">2</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> noteLength </span><span class="pun">-</span><span class="pln"> noteLength </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> thisNote</span><span class="pun">];</span><span class="pln">

    </span><span class="kwd">int</span><span class="pln"> noteTime </span><span class="pun">=</span><span class="pln"> </span><span class="lit">300</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> noteDuration</span><span class="pun">;</span><span class="pln">
    tone</span><span class="pun">(</span><span class="pln">SPEAKER_PIN</span><span class="pun">,</span><span class="pln"> notePitch</span><span class="pun">,</span><span class="pln"> noteTime</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">int</span><span class="pln"> pauseBetweenNotes </span><span class="pun">=</span><span class="pln"> noteTime </span><span class="pun">*</span><span class="pln"> </span><span class="lit">1.30</span><span class="pun">;</span><span class="pln">

    delay</span><span class="pun">(</span><span class="pln">pauseBetweenNotes</span><span class="pun">);</span><span class="pln">
    noTone</span><span class="pun">(</span><span class="pln">SPEAKER_PIN</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">/* Update the LEDs to reflect which days we have and haven't logged times */</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> updateLEDs</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">for</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> LED_CNT</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    digitalWrite</span><span class="pun">(</span><span class="pln">LED_BASE_PIN</span><span class="pun">,</span><span class="pln"> pastTimes</span><span class="pun">[</span><span class="lit">27</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">></span><span class="pln"> GOAL_TIME</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span>

 

  1. <span class="com">/*************************************************
  2. * pitches.h
  3. * Public Constants
  4. *************************************************/</span><span class="pln">
  5. </span><span class="com">#define</span><span class="pln"> NOTE_B0 </span><span class="lit">31</span><span class="pln">
  6. </span><span class="com">#define</span><span class="pln"> NOTE_C1 </span><span class="lit">33</span><span class="pln">
  7. </span><span class="com">#define</span><span class="pln"> NOTE_CS1 </span><span class="lit">35</span><span class="pln">
  8. </span><span class="com">#define</span><span class="pln"> NOTE_D1 </span><span class="lit">37</span><span class="pln">
  9. </span><span class="com">#define</span><span class="pln"> NOTE_DS1 </span><span class="lit">39</span><span class="pln">
  10. </span><span class="com">#define</span><span class="pln"> NOTE_E1 </span><span class="lit">41</span><span class="pln">
  11. </span><span class="com">#define</span><span class="pln"> NOTE_F1 </span><span class="lit">44</span><span class="pln">
  12. </span><span class="com">#define</span><span class="pln"> NOTE_FS1 </span><span class="lit">46</span><span class="pln">
  13. </span><span class="com">#define</span><span class="pln"> NOTE_G1 </span><span class="lit">49</span><span class="pln">
  14. </span><span class="com">#define</span><span class="pln"> NOTE_GS1 </span><span class="lit">52</span><span class="pln">
  15. </span><span class="com">#define</span><span class="pln"> NOTE_A1 </span><span class="lit">55</span><span class="pln">
  16. </span><span class="com">#define</span><span class="pln"> NOTE_AS1 </span><span class="lit">58</span><span class="pln">
  17. </span><span class="com">#define</span><span class="pln"> NOTE_B1 </span><span class="lit">62</span><span class="pln">
  18. </span><span class="com">#define</span><span class="pln"> NOTE_C2 </span><span class="lit">65</span><span class="pln">
  19. </span><span class="com">#define</span><span class="pln"> NOTE_CS2 </span><span class="lit">69</span><span class="pln">
  20. </span><span class="com">#define</span><span class="pln"> NOTE_D2 </span><span class="lit">73</span><span class="pln">
  21. </span><span class="com">#define</span><span class="pln"> NOTE_DS2 </span><span class="lit">78</span><span class="pln">
  22. </span><span class="com">#define</span><span class="pln"> NOTE_E2 </span><span class="lit">82</span><span class="pln">
  23. </span><span class="com">#define</span><span class="pln"> NOTE_F2 </span><span class="lit">87</span><span class="pln">
  24. </span><span class="com">#define</span><span class="pln"> NOTE_FS2 </span><span class="lit">93</span><span class="pln">
  25. </span><span class="com">#define</span><span class="pln"> NOTE_G2 </span><span class="lit">98</span><span class="pln">
  26. </span><span class="com">#define</span><span class="pln"> NOTE_GS2 </span><span class="lit">104</span><span class="pln">
  27. </span><span class="com">#define</span><span class="pln"> NOTE_A2 </span><span class="lit">110</span><span class="pln">
  28. </span><span class="com">#define</span><span class="pln"> NOTE_AS2 </span><span class="lit">117</span><span class="pln">
  29. </span><span class="com">#define</span><span class="pln"> NOTE_B2 </span><span class="lit">123</span><span class="pln">
  30. </span><span class="com">#define</span><span class="pln"> NOTE_C3 </span><span class="lit">131</span><span class="pln">
  31. </span><span class="com">#define</span><span class="pln"> NOTE_CS3 </span><span class="lit">139</span><span class="pln">
  32. </span><span class="com">#define</span><span class="pln"> NOTE_D3 </span><span class="lit">147</span><span class="pln">
  33. </span><span class="com">#define</span><span class="pln"> NOTE_DS3 </span><span class="lit">156</span><span class="pln">
  34. </span><span class="com">#define</span><span class="pln"> NOTE_E3 </span><span class="lit">165</span><span class="pln">
  35. </span><span class="com">#define</span><span class="pln"> NOTE_F3 </span><span class="lit">175</span><span class="pln">
  36. </span><span class="com">#define</span><span class="pln"> NOTE_FS3 </span><span class="lit">185</span><span class="pln">
  37. </span><span class="com">#define</span><span class="pln"> NOTE_G3 </span><span class="lit">196</span><span class="pln">
  38. </span><span class="com">#define</span><span class="pln"> NOTE_GS3 </span><span class="lit">208</span><span class="pln">
  39. </span><span class="com">#define</span><span class="pln"> NOTE_A3 </span><span class="lit">220</span><span class="pln">
  40. </span><span class="com">#define</span><span class="pln"> NOTE_AS3 </span><span class="lit">233</span><span class="pln">
  41. </span><span class="com">#define</span><span class="pln"> NOTE_B3 </span><span class="lit">247</span><span class="pln">
  42. </span><span class="com">#define</span><span class="pln"> NOTE_C4 </span><span class="lit">262</span><span class="pln">
  43. </span><span class="com">#define</span><span class="pln"> NOTE_CS4 </span><span class="lit">277</span><span class="pln">
  44. </span><span class="com">#define</span><span class="pln"> NOTE_D4 </span><span class="lit">294</span><span class="pln">
  45. </span><span class="com">#define</span><span class="pln"> NOTE_DS4 </span><span class="lit">311</span><span class="pln">
  46. </span><span class="com">#define</span><span class="pln"> NOTE_E4 </span><span class="lit">330</span><span class="pln">
  47. </span><span class="com">#define</span><span class="pln"> NOTE_F4 </span><span class="lit">349</span><span class="pln">
  48. </span><span class="com">#define</span><span class="pln"> NOTE_FS4 </span><span class="lit">370</span><span class="pln">
  49. </span><span class="com">#define</span><span class="pln"> NOTE_G4 </span><span class="lit">392</span><span class="pln">
  50. </span><span class="com">#define</span><span class="pln"> NOTE_GS4 </span><span class="lit">415</span><span class="pln">
  51. </span><span class="com">#define</span><span class="pln"> NOTE_A4 </span><span class="lit">440</span><span class="pln">
  52. </span><span class="com">#define</span><span class="pln"> NOTE_AS4 </span><span class="lit">466</span><span class="pln">
  53. </span><span class="com">#define</span><span class="pln"> NOTE_B4 </span><span class="lit">494</span><span class="pln">
  54. </span><span class="com">#define</span><span class="pln"> NOTE_C5 </span><span class="lit">523</span><span class="pln">
  55. </span><span class="com">#define</span><span class="pln"> NOTE_CS5 </span><span class="lit">554</span><span class="pln">
  56. </span><span class="com">#define</span><span class="pln"> NOTE_D5 </span><span class="lit">587</span><span class="pln">
  57. </span><span class="com">#define</span><span class="pln"> NOTE_DS5 </span><span class="lit">622</span><span class="pln">
  58. </span><span class="com">#define</span><span class="pln"> NOTE_E5 </span><span class="lit">659</span><span class="pln">
  59. </span><span class="com">#define</span><span class="pln"> NOTE_F5 </span><span class="lit">698</span><span class="pln">
  60. </span><span class="com">#define</span><span class="pln"> NOTE_FS5 </span><span class="lit">740</span><span class="pln">
  61. </span><span class="com">#define</span><span class="pln"> NOTE_G5 </span><span class="lit">784</span><span class="pln">
  62. </span><span class="com">#define</span><span class="pln"> NOTE_GS5 </span><span class="lit">831</span><span class="pln">
  63. </span><span class="com">#define</span><span class="pln"> NOTE_A5 </span><span class="lit">880</span><span class="pln">
  64. </span><span class="com">#define</span><span class="pln"> NOTE_AS5 </span><span class="lit">932</span><span class="pln">
  65. </span><span class="com">#define</span><span class="pln"> NOTE_B5 </span><span class="lit">988</span><span class="pln">
  66. </span><span class="com">#define</span><span class="pln"> NOTE_C6 </span><span class="lit">1047</span><span class="pln">
  67. </span><span class="com">#define</span><span class="pln"> NOTE_CS6 </span><span class="lit">1109</span><span class="pln">
  68. </span><span class="com">#define</span><span class="pln"> NOTE_D6 </span><span class="lit">1175</span><span class="pln">
  69. </span><span class="com">#define</span><span class="pln"> NOTE_DS6 </span><span class="lit">1245</span><span class="pln">
  70. </span><span class="com">#define</span><span class="pln"> NOTE_E6 </span><span class="lit">1319</span><span class="pln">
  71. </span><span class="com">#define</span><span class="pln"> NOTE_F6 </span><span class="lit">1397</span><span class="pln">
  72. </span><span class="com">#define</span><span class="pln"> NOTE_FS6 </span><span class="lit">1480</span><span class="pln">
  73. </span><span class="com">#define</span><span class="pln"> NOTE_G6 </span><span class="lit">1568</span><span class="pln">
  74. </span><span class="com">#define</span><span class="pln"> NOTE_GS6 </span><span class="lit">1661</span><span class="pln">
  75. </span><span class="com">#define</span><span class="pln"> NOTE_A6 </span><span class="lit">1760</span><span class="pln">
  76. </span><span class="com">#define</span><span class="pln"> NOTE_AS6 </span><span class="lit">1865</span><span class="pln">
  77. </span><span class="com">#define</span><span class="pln"> NOTE_B6 </span><span class="lit">1976</span><span class="pln">
  78. </span><span class="com">#define</span><span class="pln"> NOTE_C7 </span><span class="lit">2093</span><span class="pln">
  79. </span><span class="com">#define</span><span class="pln"> NOTE_CS7 </span><span class="lit">2217</span><span class="pln">
  80. </span><span class="com">#define</span><span class="pln"> NOTE_D7 </span><span class="lit">2349</span><span class="pln">
  81. </span><span class="com">#define</span><span class="pln"> NOTE_DS7 </span><span class="lit">2489</span><span class="pln">
  82. </span><span class="com">#define</span><span class="pln"> NOTE_E7 </span><span class="lit">2637</span><span class="pln">
  83. </span><span class="com">#define</span><span class="pln"> NOTE_F7 </span><span class="lit">2794</span><span class="pln">
  84. </span><span class="com">#define</span><span class="pln"> NOTE_FS7 </span><span class="lit">2960</span><span class="pln">
  85. </span><span class="com">#define</span><span class="pln"> NOTE_G7 </span><span class="lit">3136</span><span class="pln">
  86. </span><span class="com">#define</span><span class="pln"> NOTE_GS7 </span><span class="lit">3322</span><span class="pln">
  87. </span><span class="com">#define</span><span class="pln"> NOTE_A7 </span><span class="lit">3520</span><span class="pln">
  88. </span><span class="com">#define</span><span class="pln"> NOTE_AS7 </span><span class="lit">3729</span><span class="pln">
  89. </span><span class="com">#define</span><span class="pln"> NOTE_B7 </span><span class="lit">3951</span><span class="pln">
  90. </span><span class="com">#define</span><span class="pln"> NOTE_C8 </span><span class="lit">4186</span><span class="pln">
  91. </span><span class="com">#define</span><span class="pln"> NOTE_CS8 </span><span class="lit">4435</span><span class="pln">
  92. </span><span class="com">#define</span><span class="pln"> NOTE_D8 </span><span class="lit">4699</span><span class="pln">
  93. </span><span class="com">#define</span><span class="pln"> NOTE_DS8 </span><span class="lit">4978</span><span class="pln">
  94. </span>
<span class="com">/*************************************************
 * pitches.h
 * Public Constants
 *************************************************/</span><span class="pln">

</span><span class="com">#define</span><span class="pln"> NOTE_B0  </span><span class="lit">31</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_C1  </span><span class="lit">33</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_CS1 </span><span class="lit">35</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_D1  </span><span class="lit">37</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_DS1 </span><span class="lit">39</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_E1  </span><span class="lit">41</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_F1  </span><span class="lit">44</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_FS1 </span><span class="lit">46</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_G1  </span><span class="lit">49</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_GS1 </span><span class="lit">52</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_A1  </span><span class="lit">55</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_AS1 </span><span class="lit">58</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_B1  </span><span class="lit">62</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_C2  </span><span class="lit">65</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_CS2 </span><span class="lit">69</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_D2  </span><span class="lit">73</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_DS2 </span><span class="lit">78</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_E2  </span><span class="lit">82</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_F2  </span><span class="lit">87</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_FS2 </span><span class="lit">93</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_G2  </span><span class="lit">98</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_GS2 </span><span class="lit">104</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_A2  </span><span class="lit">110</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_AS2 </span><span class="lit">117</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_B2  </span><span class="lit">123</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_C3  </span><span class="lit">131</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_CS3 </span><span class="lit">139</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_D3  </span><span class="lit">147</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_DS3 </span><span class="lit">156</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_E3  </span><span class="lit">165</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_F3  </span><span class="lit">175</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_FS3 </span><span class="lit">185</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_G3  </span><span class="lit">196</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_GS3 </span><span class="lit">208</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_A3  </span><span class="lit">220</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_AS3 </span><span class="lit">233</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_B3  </span><span class="lit">247</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_C4  </span><span class="lit">262</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_CS4 </span><span class="lit">277</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_D4  </span><span class="lit">294</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_DS4 </span><span class="lit">311</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_E4  </span><span class="lit">330</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_F4  </span><span class="lit">349</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_FS4 </span><span class="lit">370</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_G4  </span><span class="lit">392</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_GS4 </span><span class="lit">415</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_A4  </span><span class="lit">440</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_AS4 </span><span class="lit">466</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_B4  </span><span class="lit">494</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_C5  </span><span class="lit">523</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_CS5 </span><span class="lit">554</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_D5  </span><span class="lit">587</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_DS5 </span><span class="lit">622</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_E5  </span><span class="lit">659</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_F5  </span><span class="lit">698</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_FS5 </span><span class="lit">740</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_G5  </span><span class="lit">784</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_GS5 </span><span class="lit">831</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_A5  </span><span class="lit">880</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_AS5 </span><span class="lit">932</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_B5  </span><span class="lit">988</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_C6  </span><span class="lit">1047</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_CS6 </span><span class="lit">1109</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_D6  </span><span class="lit">1175</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_DS6 </span><span class="lit">1245</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_E6  </span><span class="lit">1319</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_F6  </span><span class="lit">1397</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_FS6 </span><span class="lit">1480</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_G6  </span><span class="lit">1568</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_GS6 </span><span class="lit">1661</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_A6  </span><span class="lit">1760</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_AS6 </span><span class="lit">1865</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_B6  </span><span class="lit">1976</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_C7  </span><span class="lit">2093</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_CS7 </span><span class="lit">2217</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_D7  </span><span class="lit">2349</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_DS7 </span><span class="lit">2489</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_E7  </span><span class="lit">2637</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_F7  </span><span class="lit">2794</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_FS7 </span><span class="lit">2960</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_G7  </span><span class="lit">3136</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_GS7 </span><span class="lit">3322</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_A7  </span><span class="lit">3520</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_AS7 </span><span class="lit">3729</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_B7  </span><span class="lit">3951</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_C8  </span><span class="lit">4186</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_CS8 </span><span class="lit">4435</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_D8  </span><span class="lit">4699</span><span class="pln">
</span><span class="com">#define</span><span class="pln"> NOTE_DS8 </span><span class="lit">4978</span><span class="pln">
</span>