Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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.
/*----------------------------------------------//----------------------------*/