Mike Moore
/
RTOS_HW_04
RTOS homework 4
main.cpp
- Committer:
- gatedClock
- Date:
- 2013-08-18
- Revision:
- 17:cd6c76be8046
- Parent:
- 16:d7bbd641929c
- Child:
- 18:f19721f1069e
File content as of revision 17:cd6c76be8046:
/*----------------------------------------------//------------------------------ student : m-moore class : rtos directory : RTOS_HW_04 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 "rtos.h" #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 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. #define DEBOUNCE 0.16 // debounce pause duration in S. //--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. char cMetronomeOn; // 1 = allow blink. //--global_instances----------------------------//------------------------------ C12832_LCD lcd; // LCD object. InterruptIn iJoyStickUp (p15); // joystick up rising edge. InterruptIn iJoyStickDown (p12); // joystick down rising edge. InterruptIn iJoyStickLeft (p13); // joystick left rising edge. InterruptIn iJoyStickRight (p16); // joystick right rising edge. InterruptIn iJoyStickCenter(p14); // 1 if joystick middle pressed. DigitalIn dJoyStickUp (p15); // joystick up sample. DigitalIn dJoyStickDown (p12); // joystick down sample. DigitalIn dJoyStickLeft (p13); // joystick left sample. DigitalIn dJoyStickRight (p16); // joystick right sample. DigitalIn dJoyStickCenter(p14); // joystick center sample. 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. Timeout timeoutMetronome; //-------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. void ISR_up(); void ISR_down(); void ISR_right_rising(); void ISR_right_falling(); void ISR_left_rising(); void ISR_left_falling(); void ISR_center(); void turn_off_metronome(); //==============================================//============================== int main(void) { iJoyStickUp.rise(&ISR_up); iJoyStickDown.rise(&ISR_down); iJoyStickLeft.rise(&ISR_left_rising); iJoyStickLeft.fall(&ISR_left_falling); iJoyStickRight.rise(&ISR_right_rising); iJoyStickRight.fall(&ISR_right_falling); iJoyStickCenter.rise(&ISR_center); initialization(); // metronome ticker. tickerMetronome.attach(&interrupt_service_M,fMetroDelay); // LCD ticker. tickerLCD.attach(&lcd_display,LCDSAMPLERATE); while(1) { wait(10.0); } } /*----------------------------------------------//----------------------------*/ void initialization(void) // program initializations. { dMetroBPM = 60; // initialize to 60BPM. fMetroDelay = 60.0 / (float) (dMetroBPM); fMetroDuty = PULSELENGTH; // initialize LED on-duration. lUpDownHowMany = 0; cMetronomeOn = 0; } /*----------------------------------------------//----------------------------*/ void ISR_left_rising(void) // increase BPM. { __disable_irq(); dMetroBPM++; // increase BPM. // saturate metronome BPM. if (dMetroBPM > METROMAX) dMetroBPM = METROMAX; if (dMetroBPM < METROMIN) dMetroBPM = METROMIN; wait(DEBOUNCE); // debounce time. __enable_irq(); } /*----------------------------------------------//----------------------------*/ void ISR_left_falling(void) // ignore rising after falling edge. { __disable_irq(); wait(DEBOUNCE); // debounce time. __enable_irq(); } /*----------------------------------------------//----------------------------*/ void ISR_right_rising(void) // decrease BPM. { __disable_irq(); dMetroBPM--; // decrease BPM. // saturate metronome BPM. if (dMetroBPM > METROMAX) dMetroBPM = METROMAX; if (dMetroBPM < METROMIN) dMetroBPM = METROMIN; wait(DEBOUNCE); // debounce time. __enable_irq(); } /*----------------------------------------------//----------------------------*/ void ISR_right_falling(void) // ignore rising after falling edge. { __disable_irq(); wait(DEBOUNCE); // debounce time. __enable_irq(); } /*----------------------------------------------//----------------------------*/ void ISR_up(void) { cMetronomeOn = 0; } /*----------------------------------------------//----------------------------*/ void ISR_down(void) { cMetronomeOn = 1; timeoutMetronome.detach(); timeoutMetronome.attach(&turn_off_metronome,METROTIME); } /*----------------------------------------------//----------------------------*/ void ISR_center(void) // set BPM = 60. { dMetroBPM = 60; } /*----------------------------------------------//----------------------------*/ void lcd_display(void) // display metronome info. { lcd.cls(); // clear display. LCD1; // line 1. if (cMetronomeOn) lcd.printf(" metronome ON"); else lcd.printf(" metronome OFF"); 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 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. /*----------------------------------------------//----------------------------*/