Mike Moore
/
RTOS_HW_04
RTOS homework 4
Diff: main.cpp
- Revision:
- 0:1013288b8e43
- Child:
- 1:5f41e2df0e85
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun Aug 18 14:45:13 2013 +0000 @@ -0,0 +1,197 @@ +/*----------------------------------------------//------------------------------ + student : m-moore + class : rtos + directory : RTOS_HW_03 part 1 + file : main.cpp +----description---------------------------------//------------------------------ + Joystick-Controlled Metronome + + features: + 1. post-initialization functionality all timer-driven. + 2. IRSs contain no blocking functions. + 3. LED shows the metronome beat. + 4. metronome speed controlled with up/down joystick. + 5. rate-of-speed-change depends on how long the up/down has been active. + 6. Beat-Per-Minute (BPM) shown on LCD display. + + controls: + 1. joystick-up - increase metronome rate. + 2. joystick-down - decrease metronome rate. + 3. joystick-center - set metronome to 60BPM. + + notes: + + testing: + 1. confirm ease of being able to adjust one BPM rate with joystick up/down. + 2. confirm three joystick up/down change rates, if keeping the stick pressed. + 3. confirm max/min BPS saturation & display. + 4. confirm joystick up/down control works to change display & LED BPM. + 5. confirm joystick center-press sets rate to 60BPM immediately. + 6. confirm long-test does not result in a crash. + -> all items confirmed. + +-----includes-----------------------------------//----------------------------*/ + #include "mbed.h" // mbed class. + #include "C12832_lcd.h" // LCD class. +//---defines------------------------------------//------------------------------ + #define LCD1 lcd.locate(0, 0); // LCD line 1. + #define LCD2 lcd.locate(0,11); // LCD line 2. + #define LCD3 lcd.locate(0,22); // LCD line 3. + + #define METROMAX 800 // max. beats per minute. + #define METROMIN 8 // min. beats per minute. + #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. +//--global_definitions--------------------------//------------------------------ +//--global_variables----------------------------//------------------------------ + float fMetroDelay; // time between ticks, in seconds. + float fMetroDuty; // duration of metro high, in seconds. + int dMetroBPM; // master parameter. + long lUpDownHowMany; // count how long up/down joystick pressed. +//--global_instances----------------------------//------------------------------ + C12832_LCD lcd; // LCD object. + + DigitalIn joyStickUp (p15); // 1 if joystick up pressed. + DigitalIn joyStickDown (p12); // 1 if joystick down pressed. + DigitalIn joyStickCenter(p14); // 1 if joystick middle pressed. + + DigitalOut led3(LED1); // leftmost LED. + + Ticker tickerMetronome; // blinking LED. + Ticker tickerJoystickUD; // joystick up/down sample. + Ticker tickerLCD; // display ticker. + Timeout timeoutDutyCycle; // LED duty cycle delay. +//-------prototypes-----------------------------//------------------------------ + void initialization(); // initialize settings. + void lcd_display(); // display on LCD. + void interrupt_service_M(); // metronome tick. + void interrupt_service_UD(); // joystick up/down sample. + void led3_off(); // attachable LED control. + void led3_on(); // attachable LED control. +//==============================================//============================== + int main(void) + { + initialization(); // initialize settings. + + // metronome ticker. + tickerMetronome.attach(&interrupt_service_M,fMetroDelay); + + // LCD ticker. + tickerLCD.attach(&lcd_display,LCDSAMPLERATE); + + // up/down joystick sampling. + tickerJoystickUD.attach(&interrupt_service_UD,UDSAMPLERATE); + + while (1) // main loop. + { + wait(10.0); // it's all interrupt-driven. + } + } +/*----------------------------------------------//----------------------------*/ + void initialization(void) // program initializations. + { + dMetroBPM = 60; // initialize to 60BPM. + fMetroDelay = 60.0 / (float) (dMetroBPM); + fMetroDuty = PULSELENGTH; // initialize LED on-duration. + lUpDownHowMany = 0; + } +/*----------------------------------------------//----------------------------*/ + void lcd_display(void) // display metronome info. + { + lcd.cls(); // clear display. + + LCD1; // line 1. + lcd.printf(" METRONOME"); + + LCD2; // line 2. + + if (dMetroBPM == METROMIN) // BPM, with saturation notification. + lcd.printf(" %5.2d BPM minimum",dMetroBPM); + else + if (dMetroBPM == METROMAX) + lcd.printf(" %5.2d BPM maximum",dMetroBPM); + else + lcd.printf(" %5.2d BPM",dMetroBPM); + + LCD3; // line 3. + + lcd.printf(" RTOS HW 3 PART 1"); + } +/*----------------------------------------------//----------------------------*/ +// 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. + { + tickerMetronome.detach(); // only one attachment. + tickerMetronome.attach(&interrupt_service_M,fMetroDelay); + led3 = 1; + timeoutDutyCycle.attach(&led3_off,fMetroDuty); + } +/*----------------------------------------------//----------------------------*/ +// 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 (joyStickUp) // 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 (joyStickDown) // 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 (joyStickCenter) + { + 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. +/*----------------------------------------------//----------------------------*/ \ No newline at end of file