Penn CIS 441/541 Assignment. Fall 2015

Dependencies:   TextLCD mbed

main.cpp

Committer:
lucastai
Date:
2015-10-11
Revision:
0:068ad2e1c21d

File content as of revision 0:068ad2e1c21d:

#include "mbed.h"
#include "LPC17xx.h"
#include "TextLCD.h"
 
// declare hardware you're going to use, mostly copied from example code in previous assignments / Dagens piazza post
volatile unsigned short timer_count;
Serial pc(USBTX, USBRX);
TextLCD lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD20x4); // rs, e, d4-d7

// declare constants used for counting
int running = 0;
char mins_tens = '0';
char mins_ones = '0';
char seconds_tens = '0';
char seconds_ones = '0';
char ms_tens = '0';
char ms_ones = '0';


// hardware interrupt handler, adapted from code in piazza post by Dagaen
extern "C" void TIMER0_IRQHandler (void)
{
if((LPC_TIM0->IR & 0x01) == 0x01)   // if MR0 interrupt, proceed
    {
    LPC_TIM0->IR |= 1 << 0;         // Clear MR0 interrupt flag
    timer_count++;                  //increment timer_count
    }
}
 
// init the hardware interrupt (timer0), adapted same as above
void timer0_init(void)
{
    LPC_SC->PCONP |=1<1;            //timer0 power on
    LPC_SC-> PCLKSEL0 |= 1 << 2;    // set timer clock to CCLCK nondivided (1 clock cycle = 1 increment)
    LPC_TIM0->MR0 = 1000000;          //100mhz clock cycle, 1 cycle = 10ns, 10ms = 10 000 000 ns = 1M cycles
    LPC_TIM0->MCR = 3;              //interrupt and reset control
                                    //3 = Interrupt & reset timer0 on match (111) sets all three bits
    NVIC_EnableIRQ(TIMER0_IRQn);    //enable timer0 interrupt
}

// update the display with the global timer values
void update_display(void){
     // initialize the display, start at 0, paused
    // first MM
    lcd.locate(0,0);
    lcd.putc(mins_tens);
    lcd.locate(1,0);
    lcd.putc(mins_ones);
    // then : 
    lcd.locate(2,0);
    lcd.putc(':');
    // then SS
    lcd.locate(3,0);
    lcd.putc(seconds_tens);
    lcd.locate(4,0);
    lcd.putc(seconds_ones);
    // then :
    lcd.locate(5,0);
    lcd.putc(':');
    // then mS
    lcd.locate(6,0);
    lcd.putc(ms_tens);
    lcd.locate(7,0);
    lcd.putc(ms_ones);
}

// reset global values to 0
void reset(void){
    mins_tens = '0';
    mins_ones = '0';
    seconds_tens = '0';
    seconds_ones = '0';
    ms_tens = '0';
    ms_ones = '0';
}

// hw interrupt callback, deal with the keyboard input from PC
void kb_interrupt() {
    
    // get the char, put it on the PC command line
    char a = pc.getc();
    pc.putc(a);
    // if the char is S, make sure TCR's relevant bit is set
    if(a == 's'){
        // start timer
        running = 1;
        LPC_TIM0->TCR |= 1 << 0;
    // if the char is p, clear TCR, pausing the timer
    }else if (a == 'p'){
        LPC_TIM0->TCR = 0;
        running = 0;
    // if the char is r, reset the timer, potentially update display independent of clk interrupt if stopped
    }else if (a == 'r'){
        reset();
        if(!running){
            update_display();
        }
    }else{
        // do nothing for invalid char
    }
}

 
int main (void) 
{
    
    // connect the serial device (PC keybd) to the interrupt
    pc.attach(&kb_interrupt);
    
    // reset the counters, display the original 00:00:00 state
    reset();
    update_display();
    
    
    //init vars, start timer
    timer_count = 0;
    timer0_init();
    
    // main program loop
    while(true){
        // on 10ms interrupt
        if(timer_count){
            // set timer count to 0 every 10ms
            timer_count = 0;
            
            // count up on 10ms interrupt, make sure counter updates properly
            
            // update ms ones
            int msones_carry_flag = 0;
            if(ms_ones == '9'){
                ms_ones = '0';
                msones_carry_flag = 1;
            }else{
                ms_ones++;
            }
            
            // update ms tens
            int mstens_carry_flag = 0;
            if(msones_carry_flag){
                if(ms_tens == '9'){
                    ms_tens = '0';
                    mstens_carry_flag = 1;
                }else{
                    ms_tens++;
                } 
            }
            
            // update sec ones
            int seconds_ones_carry_flag = 0;
            if(mstens_carry_flag){
                if(seconds_ones == '9'){
                    seconds_ones = '0';
                    seconds_ones_carry_flag = 1;
                }else{
                    seconds_ones++;
                } 
            }
            
            // update sec tens
            int seconds_tens_carry_flag = 0;
            if(seconds_ones_carry_flag){
                if(seconds_tens == '5'){
                    seconds_tens = '0';
                    seconds_tens_carry_flag = 1;
                }else{
                    seconds_tens++;
                } 
            }
            
            // update mins ones
            int mins_ones_carry_flag = 0;
            if(seconds_tens_carry_flag){
                if(mins_ones == '9'){
                    mins_ones = '0';
                    mins_ones_carry_flag = 1;
                }else{
                    mins_ones++;
                } 
            }
            
            // update mins tens
            if(mins_ones_carry_flag){
                if(mins_ones == '9'){
                    mins_ones = '0';
                    mins_ones_carry_flag = 1;
                }else{
                    mins_ones++;
                } 
            }
            
            // update display with new vals
            update_display();
        
        }

    }   
}