/***************************************************************************

Download.c

****************************************************************************/

#include "Download.h"

 

/*-------------------------- Module Constants -----------------------------*/

const static char diskWait_ms = 2;       //max switch bounce time

const static int downloadWait_ms = 750;  //wait time per LED for DL progress

const static int blinkTime_ms = 250;     //blink time (on and off) while LEDS are blinking

 

/*------------------------- Module Definitions ----------------------------*/

typedef enum {  NOT_STARTED,

                RUNNING,

                STOPPED,

                COMPLETED,

                BLINKING

} DL_STATE_t; //internal state representation

 

/*-------------------------- Module Variables -----------------------------*/

static char waitingOnDiskEject;   //Used to ensure disk is reinserted before download begins

 

static DL_STATE_t myState;        //Internal state

static char diskIn;               //Disk status (in or out)

static char downloadProgress;     //Number between 0 and 8

static char blinkStatus;          //When in blink mode, indicates if the LEDs are on or off

 

static unsigned int lastUpdateDLTime;    //Used to update download progress

static unsigned int lastDiskTime;        //Used to update disk status (debounce the switch)

static unsigned int lastBlinkTime;       //Used to update blinking of the LEDs when in blink mode

 

/*-------------------------- Module Functions -----------------------------*/

static void advanceDisplay(void);        //Advances LED progress bar to indicate download status

static void pulseShift(void);            //Pulses the shift line for the shift register

static void checkDiskStatus(void);       //Reads the disk switch with debouncing software

 

/*---------------------------- Module Code --------------------------------*/

void initDownload(void) {

  unsigned int myTime;

 

  myState = NOT_STARTED;          //Initialize internal download state

  diskIn = !(PTM & BIT0HI);        //Read disk status

  if (diskIn)                     //If disk starts in, can’t start download until it

    waitingOnDiskEject = 1;        //is ejected and then reinserted

  else

    waitingOnDiskEject = 0;

 

  downloadProgress = 0;           //Reset download progress variable

  blinkStatus = 0;                //When blinking, the LEDs will first turn on

 

  myTime = TMRS12_GetTime();      //Update all the timer variables with the current time

  lastUpdateDLTime = myTime;      //this needs to be done to make the timing algorithms work

  lastDiskTime = myTime;

  lastBlinkTime = myTime;

 

  clearDownloadDisplay();         //turn off all LEDs

}

 

void resetDownload(void) {

  initDownload();          //reset download is just a wrapper for initDownload

}

 

char isDiskIn(void) {

  checkDiskStatus();       //read disk status with debouncing software

  return (diskIn);

}

 

void clearDownloadDisplay(void) {

   int i;

  //clear out shift register with all zeros

  for (i=0; i<10; i++) {

    PTAD = PTAD & BIT6LO;

    pulseShift();

  }

}

 

DOWNLOAD_EVENT_t checkDownloadEvents(void) {

  unsigned int myTime = TMRS12_GetTime();

  checkDiskStatus();  //read disk status with debouncing software

 

  //state machine using internal state

  switch(myState) {

    case NOT_STARTED:

      if(diskIn) {

          if (!waitingOnDiskEject) {

            myState = RUNNING;

            downloadProgress = 1;

            advanceDisplay();

            lastUpdateDLTime = myTime;

            return DOWNLOAD_STARTED_EVENT;

          }

          else {

            blinkDownloadLEDs();

            return DOWNLOAD_NO_EVENT;

          }

      }

      else {

          waitingOnDiskEject = 0;

          blinkDownloadLEDs();

          return DOWNLOAD_NO_EVENT;

      }

    break;

 

    case RUNNING:

      if(diskIn) {

        //check if enough time has passed to progress progress bar (LEDs)

        if((myTime - lastUpdateDLTime) > downloadWait_ms) {

          lastUpdateDLTime = myTime;

          downloadProgress++;

          advanceDisplay();

          //if all 8 LEDs are already lit up, download is complete

          if(downloadProgress > 8) {

            myState = COMPLETED;

            return DOWNLOAD_COMPLETE_EVENT;

          }

        }

      }

      else {

        //if disk isn’t in, download cannot progress

        myState = STOPPED;

        return DOWNLOAD_STOPPED_EVENT;

      }

    break;

 

    case STOPPED:

      if(diskIn) {

        lastUpdateDLTime = myTime;

        myState = RUNNING;

        return DOWNLOAD_STARTED_EVENT;

      }

    break;

 

    case COMPLETED:

      //once the download is complete, just blink LEDs

      blinkDownloadLEDs();

      return DOWNLOAD_COMPLETE_EVENT;

    break;

 

  }

  return DOWNLOAD_NO_EVENT;

}

 

void blinkDownloadLEDs(void) {

  char i = 0;

  unsigned int myTime = TMRS12_GetTime();

  //check if enough time has passed for the LEDs to be blinked (switch from on to off or vise versa)

  if ((myTime - lastBlinkTime) > blinkTime_ms) {

    lastBlinkTime = myTime;

    //fill shift register with zeros or ones

    for (i=0; i<8; i++) {

      if (blinkStatus)

        PTAD = PTAD & BIT6LO;

      else

        PTAD = PTAD | BIT6HI;

      pulseShift();

    }

    blinkStatus = !blinkStatus;

  }

}

 

static void checkDiskStatus(void) {

  unsigned int myTime = TMRS12_GetTime();

  //update diskIn if diskWait_ms worth of time has passed (debounce)

  if ((myTime - lastDiskTime) > diskWait_ms) {

     diskIn = !(PTM & BIT0HI);

     lastDiskTime = myTime;

  }

}

 

static void advanceDisplay(void) {

  //load a 1 into the shift register (turns on the next LED)

  PTAD = PTAD | BIT6HI;

  pulseShift();

}

 

static void pulseShift(void) {

  int j=0;

  PTAD = PTAD & BIT7LO;

  for (j=0; j<100; j++) {

  }

  PTAD = PTAD | BIT7HI;

}