RTOS homework 4

Dependencies:   C12832_lcd mbed

Revision:
17:cd6c76be8046
Parent:
16:d7bbd641929c
Child:
18:f19721f1069e
--- a/main.cpp	Sun Aug 18 19:15:12 2013 +0000
+++ b/main.cpp	Sun Aug 18 19:26:43 2013 +0000
@@ -41,6 +41,7 @@
        
     #define METROMAX       800                  // max. beats per minute.
     #define METROMIN         8                  // min. beats per minute.
+    #define METROTIME       10.0
     #define UDSAMPLERATE     0.1                // how often to sample U/D joystick.
     #define LCDSAMPLERATE    0.1                // how often to redraw the LCD.
     #define PULSELENGTH      0.0625             // how long the LED-on-time is.
@@ -125,7 +126,7 @@
       fMetroDelay    = 60.0 / (float) (dMetroBPM);
       fMetroDuty     = PULSELENGTH;             // initialize LED on-duration.
       lUpDownHowMany = 0;
-      cMetronomeOn   = 1;
+      cMetronomeOn   = 0;
     }
 /*----------------------------------------------//----------------------------*/
     void ISR_left_rising(void)                  // increase BPM.
@@ -180,13 +181,14 @@
 /*----------------------------------------------//----------------------------*/
     void ISR_up(void)
     {
+      cMetronomeOn = 0;
     }
 /*----------------------------------------------//----------------------------*/
     void ISR_down(void)
     {
       cMetronomeOn = 1;
       timeoutMetronome.detach();
-      timeoutMetronome.attach(&turn_off_metronome,10.0);
+      timeoutMetronome.attach(&turn_off_metronome,METROTIME);
     }
 /*----------------------------------------------//----------------------------*/
     void ISR_center(void)                       // set BPM = 60.
@@ -200,6 +202,7 @@
       lcd.cls();                                // clear display.
       
       LCD1;                                     // line 1.
+      
       if (cMetronomeOn)
       lcd.printf("  metronome ON");
       else
@@ -220,6 +223,86 @@
       lcd.printf("  RTOS HW 4");
     }
 /*----------------------------------------------//----------------------------*/
+//  this metronome tick ISR will self-adjust to the current user-selected
+//  metronome rate.  that has to be done here, and at the start of the function,
+//  in order to maintain a constant phase and to prevent a beat-skip.
+
+    void interrupt_service_M()                  // metronome tick.
+    {        
+      if (cMetronomeOn)
+      {
+        tickerMetronome.detach();                 // only one attachment.  
+        tickerMetronome.attach(&interrupt_service_M,fMetroDelay);      
+        led3_on();
+        timeoutDutyCycle.attach(&led3_off,fMetroDuty);
+      } else led3_off();
+    }
+/*----------------------------------------------//----------------------------*/
+    void turn_off_metronome(void)
+    {
+      cMetronomeOn = 0;
+    }
+/*----------------------------------------------//----------------------------*/
+//  this routine measures the number of seconds for which the joystick is
+//  in the up or down position.  for three ranges of time, three different
+//  BPM rates-of-change are used.  This means that as the user controls the
+//  metronome rate using the joystick, at first it will change slowly, then
+//  it will change at a moderate speed, then it will change quickly.
+//  additionally, pressing the center joystick button will bring the metronome
+//  back to 60BPM immediately, breaking BPM phase continuity.
+    void interrupt_service_UD(void)             // joystick up/down sample
+    {   
+      int  dPressedSeconds;                     // how many seconds joystick pressed.   
+      int  dMultiCount;                         // slow count rate.
+      char cDiscontinuity;                      // 1 = break phase & change BPM now.
+      
+      cDiscontinuity = 0;                       // don't break phase.
+      
+                                                // calculate slow rate period.
+      dMultiCount = (int) ((float) (1.0 / ((float) UDSAMPLERATE)));
+            
+      if (dJoyStickUp)                           // joystick up.
+      {
+                                                // rate-range calculations.
+        dPressedSeconds = (int) (((float) lUpDownHowMany) * UDSAMPLERATE);
+        if (dPressedSeconds < 5) {if (!(lUpDownHowMany % dMultiCount)) dMetroBPM ++;}
+        else
+        if (dPressedSeconds < 10) dMetroBPM++;
+        else dMetroBPM += 5;
+        lUpDownHowMany++;                       // joystick holddown time.
+      }
+      else
+      if (dJoyStickDown)                         // joystick down.
+      {
+                                                // rate-range calculations.
+        dPressedSeconds = (int) (((float) lUpDownHowMany) * UDSAMPLERATE);
+        if (dPressedSeconds < 5) {if (!(lUpDownHowMany % dMultiCount)) dMetroBPM --;}
+        else
+        if (dPressedSeconds < 10) dMetroBPM--;
+        else dMetroBPM -= 5;
+        lUpDownHowMany++;                       // joystick holddown time.
+      }
+      else lUpDownHowMany = 0;                  // clear when not up or down.
+      
+      if (dJoyStickCenter)
+      {
+        dMetroBPM      = 60;                    // center-button -> 60BPM.
+        cDiscontinuity = 1;                     // pending phase-break.
+      }
+                                                // saturate metronome BPM.
+      if (dMetroBPM > METROMAX) dMetroBPM = METROMAX;
+      if (dMetroBPM < METROMIN) dMetroBPM = METROMIN;
+      
+      fMetroDelay = 60.0 / (float) (dMetroBPM); // calculate Ticker delay time.
+      
+      if (cDiscontinuity)                       // implement 60BPS now.
+      {
+        tickerMetronome.detach();               // only one attachment.  
+        tickerMetronome.attach(&interrupt_service_M,fMetroDelay);      
+      }
+      
+    }
+/*----------------------------------------------//----------------------------*/
     void led3_off(void) {led3 = 0;}             // turn off the LED.
 /*----------------------------------------------//----------------------------*/
     void led3_on( void) {led3 = 1;}             // turn on the led.