#include <p30f4013.h>
#include <dsp.h>
#include <stdio.h>
#include <string.h>
_FOSC(CSW_FSCM_OFF & EC);
_FWDT(WDT_OFF);                 //Turn off the Watch-Dog Timer.
_FBORPOR(MCLR_EN & PWRT_OFF);   //Enable MCLR reset pin and turn off the
                                //power-up timers.
_FGS(CODE_PROT_OFF);            //Disable Code Protection
#define FOSC 1000000 /* The External oscillator/clock speed, In this example 1Mhz */
#define FCY FOSC/4 /* The instruction clock rate, which is the Oscillator divded by 4 */
#define Kout PORTF
#define D1A1 PORTBbits.RB0 /* Anode for the first digit of the clock (Most Significant digit of Hours)*/
#define D1A2 PORTBbits.RB1 /* Anode for the Second digit of the clock (Most Significant digit of Hours)*/
#define D2A1 PORTBbits.RB2 /* Anode for the Third digit of the clock (Least Significant digit of Hours)*/
#define D2A2 PORTBbits.RB3 /* Anode for the first digit of the clock (Least Significant digit of Hours)*/
#define D3A1 PORTBbits.RB4 /* Anode for the first digit of the clock (Most Significant digit of Minutes)*/
#define D3A2 PORTBbits.RB5 /* Anode for the Second digit of the clock (Most Significant digit of Minutes)*/
#define D4A1 PORTBbits.RB6 /* Even Anode for the Forth digit of the clock (Least Significant digit of Minutes)*/
#define D4A2 PORTBbits.RB7 /* Odd Anode for the Forth digit of the clock (Least Significant digit of Minutes)*/
#define HourMSDstate 0
#define HourLSDstate 1
#define MinuteMSDstate 2
#define MinuteLSDstate 3
unsigned int displaystate;
const unsigned int MSDA1[100] = {
1,1,1,1,1,1,1,1,1,1, /* Most signficant digit is 0 */
0,0,0,0,0,0,0,0,0,0, /* Most signficant digit is 1 */
1,1,1,1,1,1,1,1,1,1, /* Most signficant digit is 2 */
0,0,0,0,0,0,0,0,0,0, /* Most signficant digit is 3 */
1,1,1,1,1,1,1,1,1,1, /* Most signficant digit is 4 */
0,0,0,0,0,0,0,0,0,0, /* Most signficant digit is 5 */
1,1,1,1,1,1,1,1,1,1, /* Most signficant digit is 6 */
0,0,0,0,0,0,0,0,0,0, /* Most signficant digit is 7 */
1,1,1,1,1,1,1,1,1,1, /* Most signficant digit is 8 */
0,0,0,0,0,0,0,0,0,0  /* Most signficant digit is 9 */
}; 
const unsigned int MSDA2[100] = {
0,0,0,0,0,0,0,0,0,0, /* Most signficant digit is 0 */
1,1,1,1,1,1,1,1,1,1, /* Most signficant digit is 1 */
0,0,0,0,0,0,0,0,0,0, /* Most signficant digit is 2 */
1,1,1,1,1,1,1,1,1,1, /* Most signficant digit is 3 */
0,0,0,0,0,0,0,0,0,0, /* Most signficant digit is 4 */
1,1,1,1,1,1,1,1,1,1, /* Most signficant digit is 5 */
0,0,0,0,0,0,0,0,0,0, /* Most signficant digit is 6 */
1,1,1,1,1,1,1,1,1,1, /* Most signficant digit is 7 */
0,0,0,0,0,0,0,0,0,0, /* Most signficant digit is 8 */
1,1,1,1,1,1,1,1,1,1  /* Most signficant digit is 9 */
}; 
const unsigned int LSDA1[100] = {
1,0,1,0,1,0,1,0,1,0, /* Least signficant digit is 0 */
1,0,1,0,1,0,1,0,1,0, /* Least signficant digit is 1 */
1,0,1,0,1,0,1,0,1,0, /* Least signficant digit is 2 */
1,0,1,0,1,0,1,0,1,0, /* Least signficant digit is 3 */
1,0,1,0,1,0,1,0,1,0, /* Least signficant digit is 4 */
1,0,1,0,1,0,1,0,1,0, /* Least signficant digit is 5 */
1,0,1,0,1,0,1,0,1,0, /* Least signficant digit is 6 */
1,0,1,0,1,0,1,0,1,0, /* Least signficant digit is 7 */
1,0,1,0,1,0,1,0,1,0, /* Least signficant digit is 8 */
1,0,1,0,1,0,1,0,1,0  /* Least signficant digit is 9 */
};
const unsigned int LSDA2[100] = {
0,1,0,1,0,1,0,1,0,1, /* Least signficant digit is 0 */
0,1,0,1,0,1,0,1,0,1, /* Least signficant digit is 1 */
0,1,0,1,0,1,0,1,0,1, /* Least signficant digit is 2 */
0,1,0,1,0,1,0,1,0,1, /* Least signficant digit is 3 */
0,1,0,1,0,1,0,1,0,1, /* Least signficant digit is 4 */
0,1,0,1,0,1,0,1,0,1, /* Least signficant digit is 5 */
0,1,0,1,0,1,0,1,0,1, /* Least signficant digit is 6 */
0,1,0,1,0,1,0,1,0,1, /* Least signficant digit is 7 */
0,1,0,1,0,1,0,1,0,1, /* Least signficant digit is 8 */
0,1,0,1,0,1,0,1,0,1  /* Least signficant digit is 9 */
}; 
const unsigned char K1[100] = { 
/* This is the array for holding the value that set the cathode for the most significant digit, it repeates the hex code that sets the port to the correct value 10 times each so that it displays the correct most significant digit */
0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,
0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10
};
const unsigned char K2[100] = {
/* This is for the least significant digit. It repeates the same over and over so that the lowest digit is correct */
0x1,0x1,0x2,0x2,0x04,0x04,0x8,0x8,0x10,0x10,
0x1,0x1,0x2,0x2,0x04,0x04,0x8,0x8,0x10,0x10,
0x1,0x1,0x2,0x2,0x04,0x04,0x8,0x8,0x10,0x10,
0x1,0x1,0x2,0x2,0x04,0x04,0x8,0x8,0x10,0x10,
0x1,0x1,0x2,0x2,0x04,0x04,0x8,0x8,0x10,0x10,
0x1,0x1,0x2,0x2,0x04,0x04,0x8,0x8,0x10,0x10,
0x1,0x1,0x2,0x2,0x04,0x04,0x8,0x8,0x10,0x10,
0x1,0x1,0x2,0x2,0x04,0x04,0x8,0x8,0x10,0x10,
0x1,0x1,0x2,0x2,0x04,0x04,0x8,0x8,0x10,0x10
};
const long PR1VALUE = FCY; /*Set PR1VALUE to the value of FCY which is how many instructions per second the pic is running a second, so therefor a second is this value*/
unsigned int hours; //Holds our Hours
unsigned int minutes; //Holds our Minutes
unsigned int seconds; // Following the convention, this holds our seconds

void init(void){
  TRISF = 0;           //Set PORTF to output on the dsPIC
  TRISB = 0;           //Set PORTB to output on the dsPIC
  TRISA = 1;           //Set PORTA to input on the dsPIC
  TRISD = 1;           //Set PORTD to input on the dsPIC
  INTCON2bits.INT0EP = 1; //Enable Interrupt on External interrupt pin INT0
  IEC0bits.INT0IE = 1; //Enable Interrupt on External interrupt pin INT0
  INTCON2bits.INT1EP = 1; //Enable Interrupt on External interrupt pin INT1
  IEC1bits.INT1IE = 1; //Enable Interrupt on External interrupt pin INT1
  INTCON2bits.INT2EP = 1; //Enable Interrupt on External interrupt pin INT2
  IEC1bits.INT2IE = 1; //Enable Interrupt on External interrupt pin INT2
}

void clockstart(void){
  T1CON = 0;           //Clear the settings of Timer1
  TMR1 = 0;            //Clear Timer1
  PR1 = PR1VALUE;      //Set Timer1 to reset at external oscillator divded by 4 so it counts one second
  IEC0bits.T1IE = 1;   //Enable Timer1's interrupt
  T1CONbits.TON = 1;  //Turn on Timer1
}

void clockstop(void){
  IEC0bits.T1IE = 0;   //Enable Timer1's interrupt
  T1CONbits.TON = 0;  //Turn on Timer1
}

void clockrefreshstart(void){
  IEC0bits.T2IE = 1;   //Enable Timer2's interupt
  T2CON = 0;           //Clear the settings of Timer2
  TMR2 = 0;            //Clear Timer2
  PR2 = ((FCY/500)/6); //Set Timer2 to reset 83 times a second, to refresh all the nixies 500 times a second(500hz refresh rate
  T2CONbits.TON = 1;  //Turn on Timer2
}

void __attribute__((no_auto_psv))__attribute__((__interrupt__)) _T1Interrupt(void){
  /* This Function Keeps track of the time. The interrupt that jumps here happens once a second. */
  IFS0bits.T1IF = 0;
  if(seconds < 60){  //Count the seconds
    seconds++;
  }
  if(seconds == 60){ //If the seconds count is 60 do this
    seconds = 0; //Reset the Seconds Count
      if(minutes <= 59 && seconds == 0){//Update the minutes if the seconds are 0 and the minutes are less then 60
        minutes++;
      }
      if(minutes == 60 && seconds == 0){// Do this if the minutes are 60
        if(hours < 24 && seconds == 0){//If the hours are less then 24 and the seconds are zero increment the hour and reset the minutes
          hours++;
          minutes = 0;
        }
        if(hours == 24){//If the hours are 24 reset to zero
          hours = 0;
        }
      }
  }
}

void __attribute__((no_auto_psv))__attribute__((__interrupt__)) _T2Interrupt(void){
/* This Function Refreshs the display 500 times a second */
  IFS0bits.T2IF = 0;
  switch(displaystate){
    case HourMSDstate: //Do the first hour Digit
      D1A1 = 0;  // Clear the Display
      D1A2 = 0;
      D2A1 = 0;
      D2A2 = 0;
      D3A1 = 0;
      D3A2 = 0;
      D4A1 = 0;
      D4A2 = 0;
      Kout = 0x0;
      D1A1 = MSDA1[hours]; //Set the Anodes
      D1A2 = MSDA2[hours];
      Kout = K1[hours]; //Set the Cathode
      displaystate++; //Next time this statement executes do the next state
      break;
    case HourLSDstate:
      D1A1 = 0;
      D1A2 = 0;
      D2A1 = 0;
      D2A2 = 0;
      D3A1 = 0;
      D3A2 = 0;
      D4A1 = 0;
      D4A2 = 0;
      Kout = 0x0;
      D2A1 = LSDA1[hours];
      D2A2 = LSDA2[hours];
      Kout = K2[hours];
      displaystate++;
      break;
    case MinuteMSDstate:
      D1A1 = 0;
      D1A2 = 0;
      D2A1 = 0;
      D2A2 = 0;
      D3A1 = 0;
      D3A2 = 0;
      D4A1 = 0;
      D4A2 = 0;
      Kout = 0x0;
      D3A1 = MSDA1[hours];
      D3A2 = MSDA2[hours];
      Kout = K1[hours];
      displaystate++;
      break;
    case MinuteLSDstate:
      D1A1 = 0;
      D1A2 = 0;
      D2A1 = 0;
      D2A2 = 0;
      D3A1 = 0;
      D3A2 = 0;
      D4A1 = 0;
      D4A2 = 0;
      Kout = 0x0;
      D2A1 = LSDA1[hours];
      D2A2 = LSDA2[hours];
      Kout = K2[hours];
      displaystate = 0;
      break;
  }
}

void __attribute__((no_auto_psv))__attribute__((__interrupt__)) _INT0Interrupt(void){
  /* Handle interupt on external pin INT0. Use it to set hours. */
  IFS0bits.INT0IF = 0;
  clockstop();
  if(hours <= 23){
    hours++;
  }
  if(hours == 24){
    hours = 0;
  }
}

void __attribute__((no_auto_psv))__attribute__((__interrupt__)) _INT1Interrupt(void){
  /* Handle interupt on external pin INT1. Use it to set minutes. */
  IFS1bits.INT1IF = 0;
  clockstop();
  if(minutes <= 59){
    minutes++;
  }
  if(minutes == 60){
    minutes = 0;
  }
}

void __attribute__((no_auto_psv))__attribute__((__interrupt__)) _INT2Interrupt(void){
  /* Handle interupt on external pin INT2. Use it to reset seconds to sync clock and to start clock after setting time. */
  IFS1bits.INT2IF = 0;
  seconds = 0;
  clockstart();
}

int main(void){
  //clockstart();
  init();
  clockrefreshstart();
  while(1){
  }
}

