RTOS homework 4

Dependencies:   C12832_lcd mbed

Committer:
gatedClock
Date:
Sun Aug 18 19:26:43 2013 +0000
Revision:
17:cd6c76be8046
Parent:
16:d7bbd641929c
Child:
18:f19721f1069e
improved on/off, and LCD.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gatedClock 0:1013288b8e43 1 /*----------------------------------------------//------------------------------
gatedClock 0:1013288b8e43 2 student : m-moore
gatedClock 0:1013288b8e43 3 class : rtos
gatedClock 1:5f41e2df0e85 4 directory : RTOS_HW_04
gatedClock 0:1013288b8e43 5 file : main.cpp
gatedClock 0:1013288b8e43 6 ----description---------------------------------//------------------------------
gatedClock 0:1013288b8e43 7 Joystick-Controlled Metronome
gatedClock 0:1013288b8e43 8
gatedClock 0:1013288b8e43 9 features:
gatedClock 0:1013288b8e43 10 1. post-initialization functionality all timer-driven.
gatedClock 0:1013288b8e43 11 2. IRSs contain no blocking functions.
gatedClock 0:1013288b8e43 12 3. LED shows the metronome beat.
gatedClock 0:1013288b8e43 13 4. metronome speed controlled with up/down joystick.
gatedClock 0:1013288b8e43 14 5. rate-of-speed-change depends on how long the up/down has been active.
gatedClock 0:1013288b8e43 15 6. Beat-Per-Minute (BPM) shown on LCD display.
gatedClock 0:1013288b8e43 16
gatedClock 0:1013288b8e43 17 controls:
gatedClock 0:1013288b8e43 18 1. joystick-up - increase metronome rate.
gatedClock 0:1013288b8e43 19 2. joystick-down - decrease metronome rate.
gatedClock 0:1013288b8e43 20 3. joystick-center - set metronome to 60BPM.
gatedClock 0:1013288b8e43 21
gatedClock 0:1013288b8e43 22 notes:
gatedClock 0:1013288b8e43 23
gatedClock 0:1013288b8e43 24 testing:
gatedClock 0:1013288b8e43 25 1. confirm ease of being able to adjust one BPM rate with joystick up/down.
gatedClock 0:1013288b8e43 26 2. confirm three joystick up/down change rates, if keeping the stick pressed.
gatedClock 0:1013288b8e43 27 3. confirm max/min BPS saturation & display.
gatedClock 0:1013288b8e43 28 4. confirm joystick up/down control works to change display & LED BPM.
gatedClock 0:1013288b8e43 29 5. confirm joystick center-press sets rate to 60BPM immediately.
gatedClock 0:1013288b8e43 30 6. confirm long-test does not result in a crash.
gatedClock 0:1013288b8e43 31 -> all items confirmed.
gatedClock 0:1013288b8e43 32
gatedClock 0:1013288b8e43 33 -----includes-----------------------------------//----------------------------*/
gatedClock 0:1013288b8e43 34 #include "mbed.h" // mbed class.
gatedClock 15:7c0a94d2a439 35 // #include "rtos.h"
gatedClock 14:fb4c76ac43a1 36 #include "C12832_lcd.h" // LCD class.
gatedClock 0:1013288b8e43 37 //---defines------------------------------------//------------------------------
gatedClock 0:1013288b8e43 38 #define LCD1 lcd.locate(0, 0); // LCD line 1.
gatedClock 0:1013288b8e43 39 #define LCD2 lcd.locate(0,11); // LCD line 2.
gatedClock 0:1013288b8e43 40 #define LCD3 lcd.locate(0,22); // LCD line 3.
gatedClock 7:562f136c7681 41
gatedClock 0:1013288b8e43 42 #define METROMAX 800 // max. beats per minute.
gatedClock 0:1013288b8e43 43 #define METROMIN 8 // min. beats per minute.
gatedClock 17:cd6c76be8046 44 #define METROTIME 10.0
gatedClock 0:1013288b8e43 45 #define UDSAMPLERATE 0.1 // how often to sample U/D joystick.
gatedClock 0:1013288b8e43 46 #define LCDSAMPLERATE 0.1 // how often to redraw the LCD.
gatedClock 0:1013288b8e43 47 #define PULSELENGTH 0.0625 // how long the LED-on-time is.
gatedClock 10:4f2fa66cc430 48 #define DEBOUNCE 0.16 // debounce pause duration in S.
gatedClock 0:1013288b8e43 49 //--global_definitions--------------------------//------------------------------
gatedClock 0:1013288b8e43 50 //--global_variables----------------------------//------------------------------
gatedClock 0:1013288b8e43 51 float fMetroDelay; // time between ticks, in seconds.
gatedClock 0:1013288b8e43 52 float fMetroDuty; // duration of metro high, in seconds.
gatedClock 0:1013288b8e43 53 int dMetroBPM; // master parameter.
gatedClock 0:1013288b8e43 54 long lUpDownHowMany; // count how long up/down joystick pressed.
gatedClock 12:fab8e658ae76 55 char cMetronomeOn; // 1 = allow blink.
gatedClock 0:1013288b8e43 56 //--global_instances----------------------------//------------------------------
gatedClock 0:1013288b8e43 57 C12832_LCD lcd; // LCD object.
gatedClock 0:1013288b8e43 58
gatedClock 7:562f136c7681 59 InterruptIn iJoyStickUp (p15); // joystick up rising edge.
gatedClock 7:562f136c7681 60 InterruptIn iJoyStickDown (p12); // joystick down rising edge.
gatedClock 7:562f136c7681 61 InterruptIn iJoyStickLeft (p13); // joystick left rising edge.
gatedClock 7:562f136c7681 62 InterruptIn iJoyStickRight (p16); // joystick right rising edge.
gatedClock 7:562f136c7681 63 InterruptIn iJoyStickCenter(p14); // 1 if joystick middle pressed.
gatedClock 3:8ff0c9c853be 64
gatedClock 8:95f4f470ae28 65 DigitalIn dJoyStickUp (p15); // joystick up sample.
gatedClock 8:95f4f470ae28 66 DigitalIn dJoyStickDown (p12); // joystick down sample.
gatedClock 8:95f4f470ae28 67 DigitalIn dJoyStickLeft (p13); // joystick left sample.
gatedClock 8:95f4f470ae28 68 DigitalIn dJoyStickRight (p16); // joystick right sample.
gatedClock 8:95f4f470ae28 69 DigitalIn dJoyStickCenter(p14); // joystick center sample.
gatedClock 0:1013288b8e43 70
gatedClock 0:1013288b8e43 71 DigitalOut led3(LED1); // leftmost LED.
gatedClock 0:1013288b8e43 72
gatedClock 0:1013288b8e43 73 Ticker tickerMetronome; // blinking LED.
gatedClock 0:1013288b8e43 74 Ticker tickerJoystickUD; // joystick up/down sample.
gatedClock 0:1013288b8e43 75 Ticker tickerLCD; // display ticker.
gatedClock 0:1013288b8e43 76 Timeout timeoutDutyCycle; // LED duty cycle delay.
gatedClock 12:fab8e658ae76 77 Timeout timeoutMetronome;
gatedClock 0:1013288b8e43 78 //-------prototypes-----------------------------//------------------------------
gatedClock 0:1013288b8e43 79 void initialization(); // initialize settings.
gatedClock 0:1013288b8e43 80 void lcd_display(); // display on LCD.
gatedClock 0:1013288b8e43 81 void interrupt_service_M(); // metronome tick.
gatedClock 0:1013288b8e43 82 void interrupt_service_UD(); // joystick up/down sample.
gatedClock 0:1013288b8e43 83 void led3_off(); // attachable LED control.
gatedClock 0:1013288b8e43 84 void led3_on(); // attachable LED control.
gatedClock 1:5f41e2df0e85 85 void ISR_up();
gatedClock 1:5f41e2df0e85 86 void ISR_down();
gatedClock 10:4f2fa66cc430 87 void ISR_right_rising();
gatedClock 10:4f2fa66cc430 88 void ISR_right_falling();
gatedClock 11:e764ed79553a 89 void ISR_left_rising();
gatedClock 11:e764ed79553a 90 void ISR_left_falling();
gatedClock 1:5f41e2df0e85 91 void ISR_center();
gatedClock 12:fab8e658ae76 92 void turn_off_metronome();
gatedClock 0:1013288b8e43 93 //==============================================//==============================
gatedClock 0:1013288b8e43 94 int main(void)
gatedClock 0:1013288b8e43 95 {
gatedClock 3:8ff0c9c853be 96 iJoyStickUp.rise(&ISR_up);
gatedClock 5:faa6d8a04501 97 iJoyStickDown.rise(&ISR_down);
gatedClock 11:e764ed79553a 98
gatedClock 11:e764ed79553a 99 iJoyStickLeft.rise(&ISR_left_rising);
gatedClock 11:e764ed79553a 100 iJoyStickLeft.fall(&ISR_left_falling);
gatedClock 10:4f2fa66cc430 101
gatedClock 10:4f2fa66cc430 102 iJoyStickRight.rise(&ISR_right_rising);
gatedClock 10:4f2fa66cc430 103 iJoyStickRight.fall(&ISR_right_falling);
gatedClock 10:4f2fa66cc430 104
gatedClock 5:faa6d8a04501 105 iJoyStickCenter.rise(&ISR_center);
gatedClock 6:bb5f989e3425 106
gatedClock 6:bb5f989e3425 107 initialization();
gatedClock 6:bb5f989e3425 108
gatedClock 6:bb5f989e3425 109 // metronome ticker.
gatedClock 15:7c0a94d2a439 110 tickerMetronome.attach(&interrupt_service_M,fMetroDelay);
gatedClock 6:bb5f989e3425 111
gatedClock 15:7c0a94d2a439 112 // LCD ticker.
gatedClock 15:7c0a94d2a439 113 tickerLCD.attach(&lcd_display,LCDSAMPLERATE);
gatedClock 6:bb5f989e3425 114
gatedClock 6:bb5f989e3425 115 while(1)
gatedClock 6:bb5f989e3425 116 {
gatedClock 6:bb5f989e3425 117
gatedClock 6:bb5f989e3425 118 wait(10.0);
gatedClock 6:bb5f989e3425 119 }
gatedClock 2:1a3acbc4d799 120
gatedClock 0:1013288b8e43 121 }
gatedClock 0:1013288b8e43 122 /*----------------------------------------------//----------------------------*/
gatedClock 0:1013288b8e43 123 void initialization(void) // program initializations.
gatedClock 0:1013288b8e43 124 {
gatedClock 0:1013288b8e43 125 dMetroBPM = 60; // initialize to 60BPM.
gatedClock 0:1013288b8e43 126 fMetroDelay = 60.0 / (float) (dMetroBPM);
gatedClock 0:1013288b8e43 127 fMetroDuty = PULSELENGTH; // initialize LED on-duration.
gatedClock 0:1013288b8e43 128 lUpDownHowMany = 0;
gatedClock 17:cd6c76be8046 129 cMetronomeOn = 0;
gatedClock 0:1013288b8e43 130 }
gatedClock 0:1013288b8e43 131 /*----------------------------------------------//----------------------------*/
gatedClock 11:e764ed79553a 132 void ISR_left_rising(void) // increase BPM.
gatedClock 1:5f41e2df0e85 133 {
gatedClock 11:e764ed79553a 134 __disable_irq();
gatedClock 11:e764ed79553a 135
gatedClock 11:e764ed79553a 136 dMetroBPM++; // increase BPM.
gatedClock 11:e764ed79553a 137
gatedClock 12:fab8e658ae76 138 // saturate metronome BPM.
gatedClock 12:fab8e658ae76 139 if (dMetroBPM > METROMAX) dMetroBPM = METROMAX;
gatedClock 12:fab8e658ae76 140 if (dMetroBPM < METROMIN) dMetroBPM = METROMIN;
gatedClock 12:fab8e658ae76 141
gatedClock 11:e764ed79553a 142 wait(DEBOUNCE); // debounce time.
gatedClock 11:e764ed79553a 143
gatedClock 11:e764ed79553a 144 __enable_irq();
gatedClock 1:5f41e2df0e85 145 }
gatedClock 1:5f41e2df0e85 146 /*----------------------------------------------//----------------------------*/
gatedClock 11:e764ed79553a 147 void ISR_left_falling(void) // ignore rising after falling edge.
gatedClock 11:e764ed79553a 148 {
gatedClock 11:e764ed79553a 149 __disable_irq();
gatedClock 11:e764ed79553a 150
gatedClock 11:e764ed79553a 151 wait(DEBOUNCE); // debounce time.
gatedClock 11:e764ed79553a 152
gatedClock 11:e764ed79553a 153 __enable_irq();
gatedClock 11:e764ed79553a 154 }
gatedClock 11:e764ed79553a 155 /*----------------------------------------------//----------------------------*/
gatedClock 11:e764ed79553a 156
gatedClock 10:4f2fa66cc430 157 void ISR_right_rising(void) // decrease BPM.
gatedClock 4:67d958cc00e8 158 {
gatedClock 10:4f2fa66cc430 159 __disable_irq();
gatedClock 10:4f2fa66cc430 160
gatedClock 10:4f2fa66cc430 161 dMetroBPM--; // decrease BPM.
gatedClock 4:67d958cc00e8 162
gatedClock 12:fab8e658ae76 163 // saturate metronome BPM.
gatedClock 12:fab8e658ae76 164 if (dMetroBPM > METROMAX) dMetroBPM = METROMAX;
gatedClock 12:fab8e658ae76 165 if (dMetroBPM < METROMIN) dMetroBPM = METROMIN;
gatedClock 12:fab8e658ae76 166
gatedClock 10:4f2fa66cc430 167 wait(DEBOUNCE); // debounce time.
gatedClock 9:ea97a69b9b93 168
gatedClock 10:4f2fa66cc430 169 __enable_irq();
gatedClock 12:fab8e658ae76 170
gatedClock 10:4f2fa66cc430 171 }
gatedClock 10:4f2fa66cc430 172 /*----------------------------------------------//----------------------------*/
gatedClock 10:4f2fa66cc430 173 void ISR_right_falling(void) // ignore rising after falling edge.
gatedClock 10:4f2fa66cc430 174 {
gatedClock 10:4f2fa66cc430 175 __disable_irq();
gatedClock 10:4f2fa66cc430 176
gatedClock 10:4f2fa66cc430 177 wait(DEBOUNCE); // debounce time.
gatedClock 10:4f2fa66cc430 178
gatedClock 10:4f2fa66cc430 179 __enable_irq();
gatedClock 4:67d958cc00e8 180 }
gatedClock 4:67d958cc00e8 181 /*----------------------------------------------//----------------------------*/
gatedClock 4:67d958cc00e8 182 void ISR_up(void)
gatedClock 1:5f41e2df0e85 183 {
gatedClock 17:cd6c76be8046 184 cMetronomeOn = 0;
gatedClock 1:5f41e2df0e85 185 }
gatedClock 1:5f41e2df0e85 186 /*----------------------------------------------//----------------------------*/
gatedClock 4:67d958cc00e8 187 void ISR_down(void)
gatedClock 1:5f41e2df0e85 188 {
gatedClock 12:fab8e658ae76 189 cMetronomeOn = 1;
gatedClock 12:fab8e658ae76 190 timeoutMetronome.detach();
gatedClock 17:cd6c76be8046 191 timeoutMetronome.attach(&turn_off_metronome,METROTIME);
gatedClock 1:5f41e2df0e85 192 }
gatedClock 1:5f41e2df0e85 193 /*----------------------------------------------//----------------------------*/
gatedClock 3:8ff0c9c853be 194 void ISR_center(void) // set BPM = 60.
gatedClock 1:5f41e2df0e85 195 {
gatedClock 8:95f4f470ae28 196 dMetroBPM = 60;
gatedClock 4:67d958cc00e8 197
gatedClock 1:5f41e2df0e85 198 }
gatedClock 1:5f41e2df0e85 199 /*----------------------------------------------//----------------------------*/
gatedClock 0:1013288b8e43 200 void lcd_display(void) // display metronome info.
gatedClock 0:1013288b8e43 201 {
gatedClock 0:1013288b8e43 202 lcd.cls(); // clear display.
gatedClock 0:1013288b8e43 203
gatedClock 0:1013288b8e43 204 LCD1; // line 1.
gatedClock 17:cd6c76be8046 205
gatedClock 16:d7bbd641929c 206 if (cMetronomeOn)
gatedClock 16:d7bbd641929c 207 lcd.printf(" metronome ON");
gatedClock 16:d7bbd641929c 208 else
gatedClock 16:d7bbd641929c 209 lcd.printf(" metronome OFF");
gatedClock 0:1013288b8e43 210
gatedClock 0:1013288b8e43 211 LCD2; // line 2.
gatedClock 0:1013288b8e43 212
gatedClock 0:1013288b8e43 213 if (dMetroBPM == METROMIN) // BPM, with saturation notification.
gatedClock 0:1013288b8e43 214 lcd.printf(" %5.2d BPM minimum",dMetroBPM);
gatedClock 0:1013288b8e43 215 else
gatedClock 0:1013288b8e43 216 if (dMetroBPM == METROMAX)
gatedClock 0:1013288b8e43 217 lcd.printf(" %5.2d BPM maximum",dMetroBPM);
gatedClock 0:1013288b8e43 218 else
gatedClock 0:1013288b8e43 219 lcd.printf(" %5.2d BPM",dMetroBPM);
gatedClock 0:1013288b8e43 220
gatedClock 0:1013288b8e43 221 LCD3; // line 3.
gatedClock 0:1013288b8e43 222
gatedClock 8:95f4f470ae28 223 lcd.printf(" RTOS HW 4");
gatedClock 0:1013288b8e43 224 }
gatedClock 0:1013288b8e43 225 /*----------------------------------------------//----------------------------*/
gatedClock 17:cd6c76be8046 226 // this metronome tick ISR will self-adjust to the current user-selected
gatedClock 17:cd6c76be8046 227 // metronome rate. that has to be done here, and at the start of the function,
gatedClock 17:cd6c76be8046 228 // in order to maintain a constant phase and to prevent a beat-skip.
gatedClock 17:cd6c76be8046 229
gatedClock 17:cd6c76be8046 230 void interrupt_service_M() // metronome tick.
gatedClock 17:cd6c76be8046 231 {
gatedClock 17:cd6c76be8046 232 if (cMetronomeOn)
gatedClock 17:cd6c76be8046 233 {
gatedClock 17:cd6c76be8046 234 tickerMetronome.detach(); // only one attachment.
gatedClock 17:cd6c76be8046 235 tickerMetronome.attach(&interrupt_service_M,fMetroDelay);
gatedClock 17:cd6c76be8046 236 led3_on();
gatedClock 17:cd6c76be8046 237 timeoutDutyCycle.attach(&led3_off,fMetroDuty);
gatedClock 17:cd6c76be8046 238 } else led3_off();
gatedClock 17:cd6c76be8046 239 }
gatedClock 17:cd6c76be8046 240 /*----------------------------------------------//----------------------------*/
gatedClock 17:cd6c76be8046 241 void turn_off_metronome(void)
gatedClock 17:cd6c76be8046 242 {
gatedClock 17:cd6c76be8046 243 cMetronomeOn = 0;
gatedClock 17:cd6c76be8046 244 }
gatedClock 17:cd6c76be8046 245 /*----------------------------------------------//----------------------------*/
gatedClock 17:cd6c76be8046 246 // this routine measures the number of seconds for which the joystick is
gatedClock 17:cd6c76be8046 247 // in the up or down position. for three ranges of time, three different
gatedClock 17:cd6c76be8046 248 // BPM rates-of-change are used. This means that as the user controls the
gatedClock 17:cd6c76be8046 249 // metronome rate using the joystick, at first it will change slowly, then
gatedClock 17:cd6c76be8046 250 // it will change at a moderate speed, then it will change quickly.
gatedClock 17:cd6c76be8046 251 // additionally, pressing the center joystick button will bring the metronome
gatedClock 17:cd6c76be8046 252 // back to 60BPM immediately, breaking BPM phase continuity.
gatedClock 17:cd6c76be8046 253 void interrupt_service_UD(void) // joystick up/down sample
gatedClock 17:cd6c76be8046 254 {
gatedClock 17:cd6c76be8046 255 int dPressedSeconds; // how many seconds joystick pressed.
gatedClock 17:cd6c76be8046 256 int dMultiCount; // slow count rate.
gatedClock 17:cd6c76be8046 257 char cDiscontinuity; // 1 = break phase & change BPM now.
gatedClock 17:cd6c76be8046 258
gatedClock 17:cd6c76be8046 259 cDiscontinuity = 0; // don't break phase.
gatedClock 17:cd6c76be8046 260
gatedClock 17:cd6c76be8046 261 // calculate slow rate period.
gatedClock 17:cd6c76be8046 262 dMultiCount = (int) ((float) (1.0 / ((float) UDSAMPLERATE)));
gatedClock 17:cd6c76be8046 263
gatedClock 17:cd6c76be8046 264 if (dJoyStickUp) // joystick up.
gatedClock 17:cd6c76be8046 265 {
gatedClock 17:cd6c76be8046 266 // rate-range calculations.
gatedClock 17:cd6c76be8046 267 dPressedSeconds = (int) (((float) lUpDownHowMany) * UDSAMPLERATE);
gatedClock 17:cd6c76be8046 268 if (dPressedSeconds < 5) {if (!(lUpDownHowMany % dMultiCount)) dMetroBPM ++;}
gatedClock 17:cd6c76be8046 269 else
gatedClock 17:cd6c76be8046 270 if (dPressedSeconds < 10) dMetroBPM++;
gatedClock 17:cd6c76be8046 271 else dMetroBPM += 5;
gatedClock 17:cd6c76be8046 272 lUpDownHowMany++; // joystick holddown time.
gatedClock 17:cd6c76be8046 273 }
gatedClock 17:cd6c76be8046 274 else
gatedClock 17:cd6c76be8046 275 if (dJoyStickDown) // joystick down.
gatedClock 17:cd6c76be8046 276 {
gatedClock 17:cd6c76be8046 277 // rate-range calculations.
gatedClock 17:cd6c76be8046 278 dPressedSeconds = (int) (((float) lUpDownHowMany) * UDSAMPLERATE);
gatedClock 17:cd6c76be8046 279 if (dPressedSeconds < 5) {if (!(lUpDownHowMany % dMultiCount)) dMetroBPM --;}
gatedClock 17:cd6c76be8046 280 else
gatedClock 17:cd6c76be8046 281 if (dPressedSeconds < 10) dMetroBPM--;
gatedClock 17:cd6c76be8046 282 else dMetroBPM -= 5;
gatedClock 17:cd6c76be8046 283 lUpDownHowMany++; // joystick holddown time.
gatedClock 17:cd6c76be8046 284 }
gatedClock 17:cd6c76be8046 285 else lUpDownHowMany = 0; // clear when not up or down.
gatedClock 17:cd6c76be8046 286
gatedClock 17:cd6c76be8046 287 if (dJoyStickCenter)
gatedClock 17:cd6c76be8046 288 {
gatedClock 17:cd6c76be8046 289 dMetroBPM = 60; // center-button -> 60BPM.
gatedClock 17:cd6c76be8046 290 cDiscontinuity = 1; // pending phase-break.
gatedClock 17:cd6c76be8046 291 }
gatedClock 17:cd6c76be8046 292 // saturate metronome BPM.
gatedClock 17:cd6c76be8046 293 if (dMetroBPM > METROMAX) dMetroBPM = METROMAX;
gatedClock 17:cd6c76be8046 294 if (dMetroBPM < METROMIN) dMetroBPM = METROMIN;
gatedClock 17:cd6c76be8046 295
gatedClock 17:cd6c76be8046 296 fMetroDelay = 60.0 / (float) (dMetroBPM); // calculate Ticker delay time.
gatedClock 17:cd6c76be8046 297
gatedClock 17:cd6c76be8046 298 if (cDiscontinuity) // implement 60BPS now.
gatedClock 17:cd6c76be8046 299 {
gatedClock 17:cd6c76be8046 300 tickerMetronome.detach(); // only one attachment.
gatedClock 17:cd6c76be8046 301 tickerMetronome.attach(&interrupt_service_M,fMetroDelay);
gatedClock 17:cd6c76be8046 302 }
gatedClock 17:cd6c76be8046 303
gatedClock 17:cd6c76be8046 304 }
gatedClock 17:cd6c76be8046 305 /*----------------------------------------------//----------------------------*/
gatedClock 0:1013288b8e43 306 void led3_off(void) {led3 = 0;} // turn off the LED.
gatedClock 0:1013288b8e43 307 /*----------------------------------------------//----------------------------*/
gatedClock 0:1013288b8e43 308 void led3_on( void) {led3 = 1;} // turn on the led.
gatedClock 15:7c0a94d2a439 309 /*----------------------------------------------//----------------------------*/