CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

SPI with MAX7219 and MAX31855
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
edbfmi1



Joined: 18 Jul 2006
Posts: 94

View user's profile Send private message

SPI with MAX7219 and MAX31855
PostPosted: Tue Sep 06, 2016 10:00 am     Reply with quote

Hello all,

I have a project that uses an MAX31855 temperature sensor IC and an MAX7219 display driver.

I am using the PIC 16F1939 IC on this project and using the Hardware SPI port. The CCS Compiler Version I am using is 4.140

My problem is that I can get the MAX7219 to work using setup_spi.
Code:
setup_spi(SPI_MASTER | SPI_MODE_1 | SPI_CLK_DIV_64);

.
.
.
Code:

 void readMAX()
 {
       output_low(TEMP);
       delay_us(10);
       TempByte3=spi_read(0);
       TempByte2=spi_read(0);
       TempByte1=spi_read(0);
       TempByte0=spi_read(0);
       delay_us(10);
       output_high(TEMP);
 }


And I can get the MAX31855 to work using #use spi
Code:
#use spi(FORCE_HW, BITS=8, idle=1)

.
.
.
Code:

void maxsend()            //send routine for max7219
{
   output_low(DISP_OUT);                     
   spi_xfer(address);      //send address
   spi_xfer(data);         //send data
   output_high(DISP_OUT);
}


But I can't figure out how to get them both to work using either "spi setup" or "#use spi"
Any help would be appreciated.
Thanks


Last edited by edbfmi1 on Tue Sep 06, 2016 12:40 pm; edited 2 times in total
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Tue Sep 06, 2016 10:05 am     Reply with quote

post a schematic of how it is connected -
clearly indicating what device pins go to what pic pins
PLUS your fuses -
since the chip uses "pin select" and you could be in trouble
on that point too.

the 1939 is NOT a trivial part for fuse setup


first and foremost you are trying to "set up" with a
mangled mashup of the HARD setup with the SOFT one.
Not very kosher.
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Tue Sep 06, 2016 11:07 am     Reply with quote

This is where using streams with #use is useful.

The Max 31855 is using mode 2. It's also accepting a much faster clock than the Max 7219.

Now key is that you can switch modes by just doing a transfer with both chip selects disabled. You don't tell us your clock rate, so we can't tell how fast you are actually clocking the 7219.

So (something like):
Code:

#use spi(SPI1, MASTER, baud=100000, MODE=1, bits=8, stream=MAX7219)
#use spi(SPI1, MASTER, MODE=2, bits=8, stream=MAX31855)

//Then to talk to the 7219
       spi_xfer(MAX7219,0); //switches the stream to mode 1
       output_low(TEMP);
       delay_us(10);
       TempByte3=spi_xfer(MAX7219,0);
       TempByte2=spi_xfer(MAX7219,0);
       TempByte1=spi_xfer(MAX7219,0);
       TempByte0=spi_xfer(MAX7219,0);
       delay_us(10);
       output_high(TEMP);

//or for the 31855
   spi_xfer(MAX31855,0); //switches the stream to mode 2
   output_low(DISP_OUT);                     
   spi_xfer(MAX31855,address);      //send address
   spi_xfer(MAX31855,data);         //send data
   output_high(DISP_OUT);


By sending the dummy byte before dropping the chip select, the bus gets switched to the required mode and speed. Using streams, allows the spi_xfer to know how things have to be setup.

You will have to tweak the baud rate to match the /64 rate.

By default #use gives the fastest rate supported by the hardware.
edbfmi1



Joined: 18 Jul 2006
Posts: 94

View user's profile Send private message

PostPosted: Tue Sep 06, 2016 11:08 am     Reply with quote

Sorry I don't have the schematic readily available. But I do have the PIC connected as follows:
RC5(SDO) going to the MAX7219 DIN
RC4(SDI) going to the MAX31855 SO
RC3(SCK) going to the CLOCK pin on both ICs.
RC6 for the Chip Select on the MAX7219
RC7 for the chip select on the MAX31855.

I would like to use the Hard setup since I have the Chips wired to the pins on the PIC to take advantage of the this feature on the PIC.

I wrote 2 simple programs, one for the MAX7219 and one for the MA31855 based on the CCS Code Library.
Like I posted earlier, the both work independently but they use two different ways to setup the SPI port and I can't figure out how to convert either of them to work with the other SPI setup.

Here is the entire code for the MAX7219 Display Chip
Code:

#include <16f1938.H>
#fuses XT, NOWDT, NOPROTECT, NOBROWNOUT, NOPUT   // Set fuses
#use delay(clock = 4000000)

#use spi(FORCE_HW, BITS=8, idle=1)


#define DISP PIN_C6         // Chip Select for Display on SPI Bus

int8 address;               // address sent to MAX7219
int8 data;                  // data sent to MAX7219

void maxsend()            // send routine for max7219 to update display
{
   output_low(DISP);                     
   spi_xfer(address);      //send address
   spi_xfer(data);         //send data
   output_high(DISP);
}

void maxsetup()               //configure MAX7219 registers
{
    address=0x09, data=0x00, maxsend();     // Decode Mode: 0 = no decode
    address=0x0a, data=0x01, maxsend();     // Brightness: 0 = dim, f = brightest
    address=0x0b, data=0x03, maxsend();     // Number of Digits: 3 = 4 Digits, 7 = 8 Digits
    address=0x0f, data=0x00, maxsend();    // Test Register: 0 = Normal, 1 = Test Operation
    address=0x0c, data=0x01, maxsend();     // Shutdown: 0 = Shutdown, 1 = Normal Operation
}

void main()
{
   delay_cycles(1);
   output_high(DISP);
    maxsetup();
    while(1)
   {
      address=0x01, data=(51), maxsend();
      address=0x02, data=(121 | 128); maxsend();
      address=0x03, data=(109 | 128), maxsend();
      address=0x04, data=(48), maxsend();
      delay_ms(500);
      address=0x01, data=(51), maxsend();
      address=0x02, data=(121); maxsend();
      address=0x03, data=(109), maxsend();
      address=0x04, data=(48), maxsend();
      delay_ms(500);
      delay_cycles(1);
      
    }
 }


And here is the code for the MAX31855 Temperature Chip
Code:
#include <16F1938.h>

#fuses XT, NOWDT, NOPROTECT, NOBROWNOUT, NOPUT    // Set fuses

#use delay(clock=4000000)

#define TEMP PIN_C7   // Chip Select for MAX31855 Temperature IC
 
int1 Fvdd=0,Fgnd=0,Fopen=0,fault=0;
int8 TempByte3,TempByte2,TempByte1,TempByte0;
int16 Probe_Temp;
int16 Probe_Temp_F;
int16 Chip_Temp;
int16 Chip_Temp_F;

/*******************************************************************************
//Read SPI data
*******************************************************************************/ 
void readMAX()
{
   output_low(TEMP);
   delay_us(10);
   TempByte3=spi_read(0);
   TempByte2=spi_read(0);
   TempByte1=spi_read(0);
   TempByte0=spi_read(0);
   delay_us(10);
   output_high(TEMP);
}

/*******************************************************************************
//Fault detection.
//Returns >0 if FAULT. If necessary do a bitwise analisys to check fault source
*******************************************************************************/
int tempFault()
{
   fault=TempByte2&0x01; // pelos menos uma falha
   Fvdd=(TempByte0>>2)&0x01;
   Fgnd=(TempByte0>>1)&0x01;
   Fopen=TempByte0&0x01;
   return (fault*1+Fvdd*2,Fgnd*4,Fopen*8);
}

/*******************************************************************************
//Read thermocouple temperature
//Returns returns signed temperature in ºC approximately
*******************************************************************************/
int16 readExtTemp()
{
   int8 aux;
   int16 temp1;
   aux=TempByte2>>2;
   temp1=TempByte3;
   temp1<<=6;
   temp1+=aux;
   Probe_Temp = temp1/4;
   Probe_Temp_F = (Probe_Temp*9/5)+32;
   return temp1/=4;
}

/*******************************************************************************
//Read internal temperature
//Returns signed temperature in ºC approximately
*******************************************************************************/
int16 readIntTemp()
{
   int8 aux;
   int16 temp2;
   temp2=TempByte1;
   temp2<<=4;
   aux=TempByte0>>4;
   temp2=TempByte1<<4;
   temp2+=aux;       
   Chip_Temp = temp2/16;
   Chip_Temp_F = (Chip_Temp*9/5)+32;
   return temp2/=16;
}

void main()
{
   Setup_spi(SPI_MASTER );
   while(TRUE)
   {
      do
      {
          readMAX();
       }while(tempFault()!=0);
      readExtTemp();
      readIntTemp();
      delay_ms(500);
   }
}
edbfmi1



Joined: 18 Jul 2006
Posts: 94

View user's profile Send private message

PostPosted: Tue Sep 06, 2016 12:14 pm     Reply with quote

Thanks for the help so far.
I made a mistake when I originally listed the code. I had the MAX7219 and MAX31855 reversed.

I rewrote the two sample programs per Ttelmah suggestions and once again they both worked independently but when I merged them into one the display does not function properly.

Below are the two independent programs and then the merged program.
Can anyone see what I am missing here.

Temp Code MAX31855 (Works)
Code:
#include <16F1938.h>

#fuses XT, NOWDT, NOPROTECT, NOBROWNOUT, NOPUT    // Set fuses

#use delay(clock=4000000)
#use spi(SPI1, MASTER, baud=100000, MODE=1, bits=8, stream=MAX31855)

#define TEMP PIN_C7         // Chip Select for MAX31855 Temperature IC

int1 Fvdd=0,Fgnd=0,Fopen=0,fault=0;
int8 TempByte3,TempByte2,TempByte1,TempByte0;   // Data from MAX31855
int8 address;                           // address sent to MAX7219
int8 data;                              // data sent to MAX7219
int16 Probe_Temp;
int16 Probe_Temp_F;
int16 Chip_Temp;
int16 Chip_Temp_F;

/*******************************************************************************
//Read SPI data From MAX31855
*******************************************************************************/ 
void readMAX()
{
   spi_xfer(MAX31855,0); //switches the stream to mode 2    
   output_low(TEMP);
   delay_us(10);
   TempByte3=spi_xfer(MAX31855,0);
   TempByte2=spi_xfer(MAX31855,0);
   TempByte1=spi_xfer(MAX31855,0);
   TempByte0=spi_xfer(MAX31855,0);
   delay_us(10);
   output_high(TEMP);
}

/*******************************************************************************
//Fault detection.
//Returns >0 if FAULT. If necessary do a bitwise analisys to check fault source
*******************************************************************************/
int tempFault()
{
   fault=TempByte2&0x01;               // Checks general fault bit
   Fvdd=(TempByte0>>2)&0x01;            // Checks Probe to Vdd Fault
   Fgnd=(TempByte0>>1)&0x01;            // Checks Probe to ground Fault
   Fopen=TempByte0&0x01;               // Checks Probe Open Fault
   return (fault*1+Fvdd*2,Fgnd*4,Fopen*8);   // Returns 0 if no fault, else returns fault code
}

/*******************************************************************************
//Read thermocouple temperature
//Returns returns signed temperature in ºC approximately
*******************************************************************************/
int16 readExtTemp()
{
   int8 aux;
   int16 temp1;
   aux=TempByte2>>2;
   temp1=TempByte3;
   temp1<<=6;
   temp1+=aux;
   Probe_Temp = temp1/4;
   Probe_Temp_F = (Probe_Temp*9/5)+32;
   return temp1/=4;
}

/*******************************************************************************
//Read internal temperature
//Returns signed temperature in ºC approximately
*******************************************************************************/
int16 readIntTemp()
{
   int8 aux;
   int16 temp2;
   temp2=TempByte1;
   temp2<<=4;
   aux=TempByte0>>4;
   temp2=TempByte1<<4;
   temp2+=aux;       
   Chip_Temp = temp2/16;
   Chip_Temp_F = (Chip_Temp*9/5)+32;
   return temp2/=16;
}

void main()
{
   delay_cycles(1);
//   output_high(DISP);
   output_high(TEMP);
//    maxsetup();
   while(TRUE)
   {
      do
      {
          readMAX();
       }while(tempFault()!=0);
      readExtTemp();
      readIntTemp();
      delay_ms(500);
   }
}


Display Code MAX7219 (Works)
Code:
#include <16f1938.H>
#fuses XT, NOWDT, NOPROTECT, NOBROWNOUT, NOPUT   // Set fuses
#use delay(clock = 4000000)


#use spi(SPI1, MASTER, MODE=2, bits=8, stream=MAX7219)



#define DISP PIN_C6         // Chip Select for Display on SPI Bus

int8 address;               // address sent to MAX7219
int8 data;                  // data sent to MAX7219

void maxsend()            // send routine for max7219 to update display
{
   spi_xfer(MAX7219,0); //switches the stream to mode 1
   output_low(DISP);                     
   spi_xfer(MAX7219,address);      //send address
   spi_xfer(MAX7219,data);         //send data
   output_high(DISP);
}

void maxsetup()               //configure MAX7219 registers
{
    address=0x09, data=0x00, maxsend();     // Decode Mode: 0 = no decode
    address=0x0a, data=0x01, maxsend();     // Brightness: 0 = dim, f = brightest
    address=0x0b, data=0x03, maxsend();     // Number of Digits: 3 = 4 Digits, 7 = 8 Digits
    address=0x0f, data=0x00, maxsend();    // Test Register: 0 = Normal, 1 = Test Operation
    address=0x0c, data=0x01, maxsend();     // Shutdown: 0 = Shutdown, 1 = Normal Operation
}

void main()
{
   delay_cycles(1);
   output_high(DISP);
    maxsetup();
    while(1)
   {
      address=0x01, data=(51), maxsend();
      address=0x02, data=(121 | 128); maxsend();
      address=0x03, data=(109 | 128), maxsend();
      address=0x04, data=(48), maxsend();
      delay_ms(500);
      address=0x01, data=(51), maxsend();
      address=0x02, data=(121); maxsend();
      address=0x03, data=(109), maxsend();
      address=0x04, data=(48), maxsend();
      delay_ms(500);
      delay_cycles(1);
      
    }
 }


Combined Temp MAX31855 works but display MAX7219 Does not show correct output
Code:
#include <16F1938.h>

#fuses XT, NOWDT, NOPROTECT, NOBROWNOUT, NOPUT    // Set fuses

#use delay(clock=4000000)
#use spi(SPI1, MASTER, baud=100000, MODE=1, bits=8, stream=MAX31855)
#use spi(SPI1, MASTER, MODE=2, bits=8, stream=MAX7219)

#define TEMP PIN_C7         // Chip Select for MAX31855 Temperature IC
#define DISP PIN_C6         // Chip Select for Display on SPI Bus
 
int1 Fvdd=0,Fgnd=0,Fopen=0,fault=0;
int8 TempByte3,TempByte2,TempByte1,TempByte0;   // Data from MAX31855
int8 address;                           // address sent to MAX7219
int8 data;                              // data sent to MAX7219
int16 Probe_Temp;
int16 Probe_Temp_F;
int16 Chip_Temp;
int16 Chip_Temp_F;

/**********************************************************************************
// Send Update Display, MAX7219
**********************************************************************************/
void maxsend()            // send routine for max7219 to update display
{
   spi_xfer(MAX7219,0); //switches the stream to mode 1
   output_low(DISP);                     
   spi_xfer(MAX7219,address);      //send address
   spi_xfer(MAX7219,data);         //send data
   output_high(DISP);
}

/**********************************************************************************
// Initialize Display, MAX7219
**********************************************************************************/
void maxsetup()               //configure MAX7219 registers
{
   address=0x09, data=0x00, maxsend();     // Decode Mode: 0 = no decode
   address=0x0a, data=0x01, maxsend();     // Brightness: 0 = dim, f = brightest
   address=0x0b, data=0x03, maxsend();     // Number of Digits: 3 = 4 Digits, 7 = 8 Digits
   address=0x0f, data=0x00, maxsend();    // Test Register: 0 = Normal, 1 = Test Operation
   address=0x0c, data=0x01, maxsend();     // Shutdown: 0 = Shutdown, 1 = Normal Operation
}

/*******************************************************************************
//Read SPI data From MAX31855
*******************************************************************************/ 
void readMAX()
{
   spi_xfer(MAX31855,0); //switches the stream to mode 2    
   output_low(TEMP);
   delay_us(10);
   TempByte3=spi_xfer(MAX31855,0);
   TempByte2=spi_xfer(MAX31855,0);
   TempByte1=spi_xfer(MAX31855,0);
   TempByte0=spi_xfer(MAX31855,0);
   delay_us(10);
   output_high(TEMP);
}

/*******************************************************************************
//Fault detection.
//Returns >0 if FAULT. If necessary do a bitwise analisys to check fault source
*******************************************************************************/
int tempFault()
{
   fault=TempByte2&0x01;               // Checks general fault bit
   Fvdd=(TempByte0>>2)&0x01;            // Checks Probe to Vdd Fault
   Fgnd=(TempByte0>>1)&0x01;            // Checks Probe to ground Fault
   Fopen=TempByte0&0x01;               // Checks Probe Open Fault
   return (fault*1+Fvdd*2,Fgnd*4,Fopen*8);   // Returns 0 if no fault, else returns fault code
}

/*******************************************************************************
//Read thermocouple temperature
//Returns returns signed temperature in ºC approximately
*******************************************************************************/
int16 readExtTemp()
{
   int8 aux;
   int16 temp1;
   aux=TempByte2>>2;
   temp1=TempByte3;
   temp1<<=6;
   temp1+=aux;
   Probe_Temp = temp1/4;
   Probe_Temp_F = (Probe_Temp*9/5)+32;
   return temp1/=4;
}

/*******************************************************************************
//Read internal temperature
//Returns signed temperature in ºC approximately
*******************************************************************************/
int16 readIntTemp()
{
   int8 aux;
   int16 temp2;
   temp2=TempByte1;
   temp2<<=4;
   aux=TempByte0>>4;
   temp2=TempByte1<<4;
   temp2+=aux;       
   Chip_Temp = temp2/16;
   Chip_Temp_F = (Chip_Temp*9/5)+32;
   return temp2/=16;
}

void main()
{
   delay_cycles(1);
   output_high(DISP);
   output_high(TEMP);
    maxsetup();
   while(TRUE)
   {
      do
      {
          readMAX();
       }while(tempFault()!=0);
      readExtTemp();
      readIntTemp();
      address=0x01, data=(51), maxsend();
      address=0x02, data=(121 | 128); maxsend();
      address=0x03, data=(109 | 128), maxsend();
      address=0x04, data=(48), maxsend();
      delay_ms(500);
      address=0x01, data=(51), maxsend();
      address=0x02, data=(121); maxsend();
      address=0x03, data=(109), maxsend();
      address=0x04, data=(48), maxsend();
      delay_ms(500);
      delay_cycles(1);
      delay_ms(500);
   }
}
edbfmi1



Joined: 18 Jul 2006
Posts: 94

View user's profile Send private message

PostPosted: Tue Sep 06, 2016 2:31 pm     Reply with quote

Here is something else I have noticed:
If I remark out the lines that contain any reference to
Code:
 spi_xfer(MAX31855,0)

and remark out the line
Code:

#use spi(SPI1, MASTER, MODE=1, bits=8, baud=100000, stream=MAX31855)


The display works properly.
If I then unremark only the line
Code:

#use spi(SPI1, MASTER, MODE=1, bits=8, baud=100000, stream=MAX31855)

The display stops working again.

I am missing something on how the #use spi pre-processor directive works but I can't figure it out
edbfmi1



Joined: 18 Jul 2006
Posts: 94

View user's profile Send private message

PostPosted: Tue Sep 06, 2016 2:58 pm     Reply with quote

SOLVED!!

I looked into the MODE and realized that I can get them both to work if I configure the #USE SPI pre-processor directives as follows.
Code:

#use spi(SPI1, MASTER, MODE=0, bits=8, stream=MAX31855)
#use spi(SPI1, MASTER, MODE=0, bits=8, stream=MAX7219)

Also since I am only running the PIC at 4Mhz I can leave the "baud" rate off and run them as fast as possible.

Now onto the next part of the development.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Sep 06, 2016 3:28 pm     Reply with quote

I am glad you figured that out (that they both use Mode 0).

Here is the explanation of why each chip uses Mode 0:

The FAQ for the Max31855 says it uses Mode 1, and that is incorrect.
https://www.maximintegrated.com/en/support/faqs/max31855-faq.html
But if you look at Figure 2. Serial-Interface Timing on page 5 of the data
sheet, it shows that data is sent from the Max31855 on the falling edge
of clock, and that clock idles low. This means that the PIC will sample
the incoming data on the positive edge of clock, and this is SPI Mode 0.
https://datasheets.maximintegrated.com/en/ds/MAX31855.pdf

For the Max7219, "Figure 1 Timing Diagram" on page 6 of the data sheet
https://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf
shows that DIN is sampled on the rising edge of clock, and that clock
idles low. This is SPI Mode 0.
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Wed Sep 07, 2016 1:29 am     Reply with quote

I based the mode number on his previous code, which had IDLE set to high. Without setting anything else, this is mode2. I must admit I thought it strange that Maxim would have chips using different mode numbers (most manufacturers tend to stick to one standard), but didn't bother to check it!...
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Wed Sep 07, 2016 11:25 am     Reply with quote

Just a heads up, although a slight tangent:

The MAX31855 requires external linearization for low temps I.E. -80C.
at -80C without external linearization, this chip reads -40C...which is bad.
I never checked what the hot side was like since i didnt need it.

Maxim was nice and sent me the formulas they recommend and a little online testing app to confirm your math.

I "hijacked" the Driver thread on the library with a linearized driver that works well in my -80C application....

G
_________________
CCS PCM 5.078 & CCS PCH 5.093
edbfmi1



Joined: 18 Jul 2006
Posts: 94

View user's profile Send private message

PostPosted: Thu Mar 22, 2018 2:06 pm     Reply with quote

Well, we finally have gone into production on this unit and now I am running into problems with 10% failure rate with the display.
When I look at the data being sent to the display driver in the maxsend() subroutine in a watch window the correct data is being sent to the correct address but the display shows garbage.
In case anybody is up for a challenge I have attached the entire program.
Any help would be greatly appreciated.
I am using PCM Compiler V4.140 and MPLAB IDE v 8.92
Code:
#include <16F1518.h>
#include <24LC64.c>

#fuses XT, NOWDT, PROTECT, BROWNOUT, PUT    // Set fuses
//#fuses XT, NOWDT, NOPROTECT, BROWNOUT, NOPUT    // Set fuses USE these fuses for Debugging with PicKit3

#use delay(clock=4000000)
#use spi(SPI1, MASTER, MODE=0, bits=32, stream=MAX31855)
#use spi(SPI1, MASTER, MODE=0, bits=8, stream=MAX7219)

// Display digit assignments

#define Low 0
#define SPI_MODE_1  (SPI_L_TO_H)
#define V_MONITOR PIN_A0      // Voltage Monitoring Inpit
#define LIGHT_IN PIN_A1         // Monitor Ambient Light Input
#define HEARTBEAT PIN_A2      // Heart Beat LED
#define FAN_RY PIN_A3         // Fan Relay Output
#define STEP_2_PB PIN_A4      // STEP_2 Push Button Input
#define STEP_1_PB PIN_A5      // STEP_1 Push Button Input

#define DOWN_PB PIN_B0         // DOWN Arrow Push Button Input
#define UP_PB PIN_B1         // UP Arrow Push Button Input
#define CALI_IN PIN_B2         // Calibrate Input
#define FUEL_RY PIN_B3         // FUEL Relay Output
//PIN_B4                   Not Used
#define HIGH_LED PIN_B5         // HIGH TEMP LED Output
// PIN_B6  Reserved for ICSP_CLOCK
// PIN_B7  Reserved for ICSP_DATA

// PIN_C0 I2C DATAfs
// PIN_C1 I2C CLOCK
// PIN_C2 Available
// PIN_C3 SPI CLOCKGC
// PIN_C4 SPI DATA IN
// PIN_C5 SPI DATA OUT
#define TEMP PIN_C7         // Chip Select for MAX31855 Temperature IC
#define DISP PIN_C6       // Chip Select for Display on SPI Bus
 
int1 Fvdd=0,Fgnd=0,Fopen=0,fault=0;
int8 TempByte3,TempByte2,TempByte1,TempByte0;   // Data from MAX31855
int8 address;                           // address sent to MAX7219
int8 data;                              // data sent to MAX7219
int8 ColonOn;                           // "Or'd" with the timer to flash colon

int8 AMBIENT;               // Ambient Light Input Dark = 255, Bright Light = 0
int8 VOLTAGE;               // Input Voltage Level

int8 ten_ms_timer;      // milisecond timer
int8 tenths_timer;   // tenth of a second timer
int8 sec_timer;      // seconds timer
signed min_timer;      // minute timer
int8 hour_timer;   // hour timer
int8 FanOnTimer;   // Second timer to set the delay before Fuel Turns on

int8 msd_code;      // thousands
int8 lsd2_code;      // hunsdreds
int8 lsd1_code;      // tens
int8 lsd_code;      // ones

int8 msd_value;      // value of the msd
int8 lsd2_value;   // value of the lsd2
int8 lsd1_value;   // value of the lsd1
int8 lsd_value;      // value of the lsd

int8 temp_msd_code;      // temperature thousands
int8 temp_lsd2_code;   // temperature hunsdreds
int8 temp_lsd1_code;   // temperature tens
int8 temp_lsd_code;      // temperature ones

// int8 time_msd_code;      // time thousands
// int8 time_lsd2_code;   // time hunsdreds

// int8 time_lsd_code;      // time ones

// int16 Timer1Preset;   // Preset setting for Timer1
signed int16 Probe_Temp;
signed int16 Probe_Temp_F;         // Unsigned Probe Temperature, used for display
signed int16 Probe_Temp_Signed;    // Signed value of Probe Temp used for arithmetic
signed int16 StartTemp;   // Used to see if Temp is rising at start up
int16 Chip_Temp;
int16 Chip_Temp_F;
signed int16 TempSetPoint;      // The current temperature set point
int16 FanUpOffset;      // The Fan Off Offset going up amount
int16 FanDownOffset;   // The Fan On Offset going down
int16 FuelOffset;      // The Fuel On Offset amount
int16 FuelOnTimer;      // Used to check for temperature rise of 10 degrees within 30 seconds
int16 StartTimer;      // Used to blank the display after 2 Seconds if STEP_1_PB is not pressed
int16 TimerPausedTimer; // Used to see if STEP_1_PB is pressed twice within 1 second
int16 HeartBeatTimer;   // Timer to pulse heartbeat
int16 CoolSet;         // Cool down setting

int16 Debounce_STEP_1_PB;   // Counter for Debounicing STEP_1_PB
int16 Debounce_STEP_2_PB;   // Counter for Debounicing STEP_2_PB
int16 Debounce_UP_PB;   // Counter for Debounicing UP_PB
int16 Debounce_DOWN_PB;   // Counter for Debounicing DOWN_PB

int16 data1;            // Used to read eeProm
int16 data2;            // Used to read eeProm


int16 CountDownTimer;         // Timer value in HHMM where HH max is 24 and MM max is 60
                        // That is, the high byte is hours and low byte is minutes

int8   StatusBits1;               // Status Bits - first bank
#bit   LoadTimeDisplay = StatusBits1.0   // Used to tell when to update the time display
#bit   TimerDone = StatusBits1.1      // Set when timer has counted down to zero
#bit   FuelChange = StatusBits1.2      // Set when fuel changing
#bit   ProbeFailed = StatusBits1.3      // Set when Probe Failed
#bit   LowVoltage = StatusBits1.4      // Set when AC Line Voltage is too low
#bit   LowTemp = StatusBits1.5         // Set when negative bit is set
#bit   FanStart = StatusBits1.6      // Set when the Fan is first turmed on
#bit   FuelStart = StatusBits1.7      // Set wehn Fuel first starts

int8   StatusBits2;
#bit   TimerPaused = StatusBits2.0      // Set when timer is paused
#bit   CheckPause = StatusBits2.1      // Toggled to run the Pause routine
#bit   PausedTemp = StatusBits2.2      // Used to update the Temperature when Timer is Paused
#bit   LoPorDisp = StatusBits2.3      // Set when Lo Por is displayed
#bit   FanDownChange = StatusBits2.4   // Set when changing Fan Down Set point
#bit   TempReached = StatusBits2.5      // Set if initial temperature rise is met
#bit   NegTemp = StatusBits2.6         // Set when negative temperature is read


int8   ButtonsPressed;
#bit   STEP_1_Pressed = ButtonsPressed.0   // True when button 1 pressed
#bit   STEP_1_Held = ButtonsPressed.1      // True when button 1 held for more than 1/2 second
#bit   STEP_2_Pressed = ButtonsPressed.2   // True when button 2 pressed
#bit   STEP_2_Held = ButtonsPressed.3      // True when button 2 held for more than 1/2 second
#bit   UP_Pressed = ButtonsPressed.4      // True when UP button pressed
#bit   UP_Held = ButtonsPressed.5         // True when UP button held for more than 1/2 second
#bit   DOWN_Pressed = ButtonsPressed.6      // True when DOWN button pressed
#bit   DOWN_Held = ButtonsPressed.7      // True when DOWN button held for more than 1/2 second


/**********************************************************************************
// Setup the timer2
**********************************************************************************/
#separate
#int_TIMER2
void TIMER2_Interrupt_Servicing(void)   // 10ms interrupt
{
   HeartBeatTimer++;
   if(HeartBeatTimer == 50)
   {
      if((TimerPaused == True)&&(PausedTemp == False))      // Update Temp if timer Paused
      {
         PausedTemp = True;
      }
      output_toggle(HEARTBEAT);
      HeartBeatTimer = 0;
   }
   if((TimerPaused == True)&&(TimerPausedTimer < 100)&&(STEP_2_Pressed == False))
   {
      TimerPausedTimer++;
   }
   if((TimerPaused == True)&&(STEP_2_Pressed == True)&&(TimerPausedTimer >= 10)&&(TimerPausedTimer <= 99))
   {
      reset_cpu();
   }
   if(TimerPaused == False)
   {
      TimerPausedTimer = 0;
   }
   if ((TimerPausedTimer >=100)&&(STEP_2_Pressed == True))      
   {
      TimerPaused = False;
   }
   delay_cycles(1);               // NOP
   if(TimerDone == True)
   {
      ColonOn = 128;
   }
   delay_cycles(1);
   CheckPause = 1;            // Check pause routine ever .1seconds
   if(TimerPaused == False)
   {
      ten_ms_timer--;                  // Increment milisecond timer
   }
   if(ten_ms_timer == 0)            //
   {
      delay_cycles(1);
      if((FanOnTimer <= 100)&&(input_state(FAN_RY)))
      {
         FanOnTimer++;
      }
      if((FuelStart == True)&(FuelOnTimer <= 300))
      {
         FuelOnTimer++;
      }
      if((StartTimer <= 20))
      {
         StartTimer++;
      }
      tenths_timer++;               // Increment tenths of a second timer
      ten_ms_timer = 10;            // and reset milisecond timer
   }
   if(tenths_timer == 5)
   {
      if((ColonOn == 0)&&(TimerDone == False))
      {
         LoadTimeDisplay = true;      // Refresh the Time display
         ColonOn = 128;            //   Set the value to "or" with the display to flash timer colon
      }
   }
   if(tenths_timer == 10)
   {
      if(ColonOn == 128)
      {
         LoadTimeDisplay = true;      // Refresh the Time display
         ColonOn = 0;            //   Set the value to "or" with the display to flash timer colon
      }
      if((TimerDone == False)&&(ProbeFailed == False))
      {
         sec_timer--;               // Increment second timer
      }
      tenths_timer = 0;            // and reset tenths timer
      if(TimerDone == False)
      {
         ColonOn = 0;               //   Set the value to "or" with the display to flash timer colon
      }
   }
   if((TimerDone == False)&&(ProbeFailed == False))
   {
      if(sec_timer == 00)
      {
         sec_timer = 60;               // and reset seconds timer
         min_timer--;               // Decrement the minute timer
         if(min_timer >=0)
         {
            CountDownTimer=make16(hour_timer, min_timer); // Puts hour in highbyte and minute in low byte
         }      
      }
      if((min_timer < 0 ) && (hour_timer >=1))
      {
         min_timer = 59;               // and rest hour timer
         hour_timer--;               // Decrement the hour timer
         CountDownTimer=make16(hour_timer, min_timer);   // Puts hour in highbyte and minute in low byte
      }
   }
   if((min_timer == 0) && (hour_timer == 0))         // Countdown Finished
   {
      delay_cycles(1);
      TimerDone = True;
   }
   if(input_state(STEP_1_PB) == True)   // Step 1 Not Pressed
   {
      delay_cycles(1);
      STEP_1_Pressed = False;         // True when button 1 pressed
      STEP_1_Held = False;         // True when button 1 held for more than 1/2 second
      Debounce_STEP_1_PB = 0;         // Reset Debounce
   }
   else                        // Step 1 Pressed
   {
      delay_cycles(1);
      STEP_1_Pressed = True;         // True when button 1 pressed
      Debounce_STEP_1_PB++;         // Increment Debounce
      if(Debounce_STEP_1_PB >= 50)   // See if it was held for 1/2 second
      {
         Debounce_STEP_1_PB = 50;
         STEP_1_Held = True;
      }
   }
   if(input_state(STEP_2_PB) == True)   // Step 2 Not Pressed
   {
      delay_cycles(1);
      STEP_2_Pressed = False;         // True when button 1 pressed
      STEP_2_Held = False;         // True when button 1 held for more than 1/2 second
      Debounce_STEP_2_PB = 0;         // Reset Debounce
   }
   else                        // Step 2 Pressed
   {
      delay_cycles(1);
      STEP_2_Pressed = True;         // True when button 1 pressed
      Debounce_STEP_2_PB++;         // Increment Debounce
      if(Debounce_STEP_2_PB >= 50)   // See if it was held for 1/2 second
      {
         Debounce_STEP_2_PB = 50;
         STEP_2_Held = True;
      }
   }
   if(input_state(UP_PB) == True)      // Up Not Pressed
   {
      delay_cycles(1);
      UP_Pressed = False;            // True when button 1 pressed
      UP_Held = False;            // True when button 1 held for more than 1/2 second
      Debounce_UP_PB = 0;            // Reset Debounce
   }
   else                        // Up Pressed
   {
      delay_cycles(1);
      UP_Pressed = True;            // True when button 1 pressed
      Debounce_UP_PB++;            // Increment Debounce
      if(Debounce_UP_PB >= 50)      // See if it was held for 1/2 second
      {
         Debounce_UP_PB = 50;
         UP_Held = True;
      }
   }
   if(input_state(DOWN_PB) == True)   // Down Not Pressed
   {
      delay_cycles(1);
      DOWN_Pressed = False;         // True when button 1 pressed
      DOWN_Held = False;            // True when button 1 held for more than 1/2 second
      Debounce_DOWN_PB = 0;         // Reset Debounce
   }
   else                        // Down Pressed
   {
      delay_cycles(1);
      DOWN_Pressed = True;         // True when button 1 pressed
      Debounce_DOWN_PB++;            // Increment Debounce
      if(Debounce_DOWN_PB >= 50)      // See if it was held for 1/2 second
      {
         Debounce_DOWN_PB = 50;
         DOWN_Held = True;
      }
   }
}

/**********************************************************************************
// Read the Analog Ports
**********************************************************************************/
void read_analog()
{
   set_adc_channel(0);               // VOLTAGE LEVEL INPUT Channel 0;
   delay_ms(1);
   VOLTAGE = read_adc();
   if(input_state(FAN_RY)&&input_state(FUEL_RY))
   {
      if(VOLTAGE <= 46-AMBIENT)
      {
         LowVoltage = True;
      }
      if (VOLTAGE >= 50-AMBIENT)
      {
         LowVoltage = False;
      }
   }
   else if (input_state(FAN_RY))
   {
      if(VOLTAGE <= 49-AMBIENT)
      {
         LowVoltage = True;
      }
      if (VOLTAGE >= 56-AMBIENT)
      {
         LowVoltage = False;
      }
   }
   else
   {
      if(VOLTAGE <= 56-AMBIENT)
      {
         LowVoltage = True;
      }
      if (VOLTAGE >= 63-AMBIENT)
      {
         LowVoltage = False;
      }
   }   
   delay_cycles(1);
   set_adc_channel(1);               // Ambient Light Analog Channel 1
   delay_ms(1);
   AMBIENT = read_adc();
   delay_cycles(1);
   if (AMBIENT <= 75)
   {
      AMBIENT = 15;
   }
   else if(AMBIENT <= 123)
   {
      AMBIENT = 11;
   }
   else if(AMBIENT <= 171)
   {
      AMBIENT = 7;
   }
   else if(AMBIENT <= 219)
   {
      AMBIENT = 3;
   }
   else
   {
      AMBIENT = 1;
   }   
   delay_cycles(1);
}

/**********************************************************************************
// Send Update Display, MAX7219
**********************************************************************************/
void maxsend()                     // send routine for max7219 to update display
{
   spi_xfer(MAX7219,0);             //switches the stream to mode 0
   delay_us(10);     
   output_low(DISP);
   delay_us(10);                     
   spi_xfer(MAX7219,address);         //send address
//   delay_us(10);     
   spi_xfer(MAX7219,data);            //send data
//   delay_us(10);
   output_high(DISP);
//   delay_us(10);
}

/**********************************************************************************
// Initialize Display, MAX7219
**********************************************************************************/
void maxsetup()                           //configure MAX7219 registers
{
   address=0x09, data=0x00, maxsend();      // Decode Mode: 0 = no decode
   address=0x0a, data=0x01, maxsend();      // Brightness: 0 = dim, f = brightest
   address=0x0b, data=0x07, maxsend();      // Number of Digits: 3 = 4 Digits, 7 = 8 Digits
   address=0x0f, data=0x00, maxsend();      // Test Register: 0 = Normal, 1 = Test Operation
   address=0x0c, data=0x01, maxsend();      // Shutdown: 0 = Shutdown, 1 = Normal Operation
}

/*******************************************************************************
//Read SPI data From MAX31855
*******************************************************************************/ 
void readMAX()
{
   int32 MAXread;
   spi_xfer(MAX31855,0);                //switches the stream to mode 0    
   output_low(TEMP);
   delay_us(10);
   MAXread=spi_xfer(MAX31855,0);
//   delay_us(10);
   output_high(TEMP);
//   delay_us(10);
   TempByte3=MAXread>>24 & 0xff;
   TempByte2=MAXread>>16 & 0xff;
   TempByte1=MAXread>>8 & 0xff;
   TempByte0=MAXread & 0xff;
}

/*******************************************************************************
//Fault detection.
//Returns >0 if FAULT. If necessary do a bitwise analisys to check fault source
*******************************************************************************/
int tempFault()
{
   fault=TempByte2&0x01;               // Checks general fault bit
   Fvdd=(TempByte0>>2)&0x01;            // Checks Probe to Vdd Fault
   Fgnd=(TempByte0>>1)&0x01;            // Checks Probe to ground Fault
   Fopen=TempByte0&0x01;               // Checks Probe Open Fault
   return (fault*1+Fvdd*2,Fgnd*4,Fopen*8);   // Returns 0 if no fault, else returns fault code
}

/*******************************************************************************
//Read thermocouple temperature
//Returns returns signed temperature in ºC approximately
*******************************************************************************/
signed int16 readExtTemp()
{
   delay_cycles(1);
   signed int16 temp1;
   temp1 = make16(TempByte3,TempByte2);
   if (!bit_test(temp1,15))               // Positive or zero degrees celsius
   {
      delay_cycles(1);
      temp1>>=2;                        // Shift out the 2 lower bits (Fault, Reserved)
      Probe_Temp = temp1>>2;               // Shift out the decimal bits
      Probe_Temp_F = (Probe_Temp*9/5) + 32;
      Probe_Temp_Signed = Probe_Temp_F;
      delay_cycles(1);
      NegTemp = False;
      return;
   }
   else                              // Negative degrees celsius
   {
      delay_cycles(1);
      temp1=~temp1;                     // Take ones compliment
      temp1>>=2;                        // Shift out the 2 lower bits (Fault, Reserved)
      temp1+=1;
      Probe_Temp = (temp1>>2);            // Shift out the decimal bits
      Probe_Temp = Probe_Temp*-1;            // Change the sign for C to F conversion
      Probe_Temp_F = (Probe_Temp*9/5) + 32;
      Probe_Temp_Signed = Probe_Temp_F;
      if (Probe_Temp_F >=0)
      {
         NegTemp = False;
      }
      else
      {
         Probe_Temp_F = Probe_Temp_F*-1;         // Change the sign for display purposes
         NegTemp = True;
      }
      delay_cycles(1);
      return;
   }      
}
/*
int16 readExtTemp()
{
   int16 aux;
   int16 temp1;
   delay_cycles(1);
   temp1=TempByte3>>7;
   delay_cycles(1);
   if(temp1 == 1)       // Check for signbit set which means negative
   {
      delay_cycles(1);
      LowTemp = True;
      Probe_Temp_F = 32;
   }
   else
   {
      delay_cycles(1);
      LowTemp = False;   
      aux=TempByte2>>2;
      temp1=TempByte3;
      temp1<<=6;
      temp1+=aux;
      Probe_Temp = temp1/4;
      Probe_Temp_F = (Probe_Temp*9/5)+32;
   }
   delay_cycles(1);
   return temp1/=4;
}
*/

/*******************************************************************************
//Read internal temperature
//Returns signed temperature in ºC approximately
*******************************************************************************/
int16 readIntTemp()
{
   int8 aux;
   int16 temp2;
   temp2=TempByte1;
   temp2<<=4;
   aux=TempByte0>>4;
   temp2=TempByte1<<4;
   temp2+=aux;       
   Chip_Temp = temp2/16;
   Chip_Temp_F = (Chip_Temp*9/5)+32;
   return temp2/=16;
}

/*******************************************************************************
// Convert numbers to 7-Segment display code
*******************************************************************************/
#separate
void display_update(int digit_code, int8 &digit_value)
{
   delay_cycles(1);
   switch(digit_code)
   {
      case 0:
         digit_value = 126;  // dig_0
         break;
      case 1:
         digit_value = 48;  // dig_1
         break;
      case 2:
         digit_value = 109;  // dig_2
         break;
      case 3:
         digit_value = 121;  // dig_3
         break;
      case 4:
         digit_value = 51;  // dig_4
         break;
      case 5:
         digit_value = 91;  // dig_5
         break;
      case 6:
         digit_value = 95;  // dig_6
         break;
      case 7:
         digit_value = 112;  // dig_7
         break;   
      case 8:
         digit_value = 127;  // dig_8
         break;
      case 9:
         digit_value = 123;  // dig_9
         break;
      case 10:
         digit_value = 0;  // dig_blank
         break;
      case 11:
         digit_value = 0b01110011;  // dig_P
         break;
      case 12:
         digit_value = 0b01010000;  // dig_r
         break;
      case 13:
         digit_value = 0b00011100;  // dig_u
         break;
      case 14:
         digit_value = 0b01010100;  // dig_n
         break;
      case 15:
         digit_value = 0b00111001;  // dig_C
         break;
      case 16:
         digit_value = 0b01000000;  // dig_-
         break;
      case 17:
         digit_value = 0b01111001;  // dig_E
   }
}

/*******************************************************************************
// Convert the timer value into the specific digits
*******************************************************************************/ 
void GetDigitsTimer(int16 preset)   // Separates the passed value into the specific digits
{
   int8 hours, minutes, minhigh, hourhigh, val;

   hours = make8(preset, 1);
   minutes = make8(preset, 0);
   delay_cycles(1);
   hourhigh = 0;
   minhigh = 0;
   val = hours;
   while (Val >= 10)
   {
      Val -= 10;
      hourhigh++;
   }
   msd_code = hourhigh;
   lsd2_code = val;

   val = minutes;
   while (Val >= 10)
   {
      Val -= 10;
      minhigh++;
   }

   lsd1_code = minhigh;
   lsd_code = val;
}

/*******************************************************************************
// Convert the temperature value into the specific digits
*******************************************************************************/ 
void GetDigitsTemp(int16 preset)   // Separates the passed value into the specific digits
{
   int8  tens, huns, thous;
   int16 val;
   tens = 0;
   huns = 0;
   thous = 0;
   val = preset;
   while (Val >= 1000)
   {
      Val -= 1000;
      thous++;
   }
 
   while (Val >= 100)
   {
      Val -= 100;
      huns++;
   }
 
   while (Val >= 10)
   {
      Val -= 10;
      tens++;
   }
   msd_code = thous;
   lsd2_code = huns;
   lsd1_code = tens;
   lsd_code = val;
}

/*******************************************************************************
// Update the Temperature Display
*******************************************************************************/
void UpdateTempDisplay(int16 preset)
{
   if(LoPorDisp == False)
   {
      display_update(lsd_code, lsd_value);
      address=0x05, data=(lsd_value), maxsend();
      if ((preset)<10)
      {
         address=0x06, data=(0), maxsend();
      }   
      else
      {
         display_update(lsd1_code, lsd1_value);
         address=0x06, data=(lsd1_value); maxsend();
      }
      if ((preset)<100)
      {
         if ((FuelChange == True)||(FanDownChange == True)||(NegTemp == True))
         {
            address=0x07, data=(1), maxsend();
            address=0x08, data=(0), maxsend();
         }
         else
         {
            address=0x07, data=(0), maxsend();
         }
      }   
      else
      {
         display_update(lsd2_code, lsd2_value);
         address=0x07, data=(lsd2_value), maxsend();
      }
      if ((preset)<1000)
      {
         if (((FuelChange == True)||(NegTemp == True)||(FanDownChange == True))&&(preset > 99))
         {
            address=0x08, data=(1), maxsend();
         }
         else
         {
            address=0x08, data=(0), maxsend();
         }
      }   
      else
      {
         display_update(msd_code, msd_value);
         address=0x08, data=(msd_value), maxsend();
      }
   }
   else
   {
      delay_cycles(1);
      LoPorDisp = False;
   }
}

/*******************************************************************************
// Update the Time Display
*******************************************************************************/
void UpdateTimeDisplay()
{
   delay_cycles(1);
   int8 hours, minutes;

   hours = make8(CountDownTimer, 1);
   minutes = make8(CountDownTimer, 0);
   delay_cycles(1);
    address=0x0a, data=AMBIENT, maxsend();     // Brightness: 0 = dim, f = brightest
   delay_cycles(1);
   if ((LowVoltage == True)&&(ColonOn == 0))
   {
      delay_cycles(1);
      address=0x08, data=0, maxsend();      // Send " "
      address=0x07, data=14, maxsend();      // Send "L"
      address=0x06, data=29, maxsend();      // Send "o"
      address=0x05, data=0, maxsend();      // Send " "
      address=0x04, data=103, maxsend();      // Send "P"
      address=0x03, data=29, maxsend();      // Send "o"
      address=0x02, data=5, maxsend();      // Send "r"
      address=0x01, data=0, maxsend();      // Send " "
      LoPorDisp = True;
      delay_cycles(1);
   }
   else
   {      
      display_update(lsd_code, lsd_value);
      address=0x01, data=(lsd_value), maxsend();
      if (((minutes)<10)&&(hours == 0))
      {
         address=0x02, data=(0 | ColonOn), maxsend();
      }   
      else
      {
         display_update(lsd1_code, lsd1_value);
         address=0x02, data=(lsd1_value | ColonOn); maxsend();
      }
      if ((hours > 0) && (hours < 10))
      {
         display_update(lsd2_code, lsd2_value);
         address=0x03, data=(lsd2_value | ColonOn), maxsend();
         address=0x04, data=0, maxsend();
      
      }
      else if (hours == 0)
      {
         address=0x03, data=(0 | ColonOn), maxsend();
         address=0x04, data=0, maxsend();
      }
      else
      {
         display_update(lsd2_code, lsd2_value);
         address=0x03, data=(lsd2_value | ColonOn), maxsend();
         display_update(msd_code, msd_value);
         address=0x04, data=(msd_value), maxsend();
      }
   }
}

/*******************************************************************************
// Temperature Change Routine
*******************************************************************************/
void TempChange()
{
   delay_cycles(1);
    address=0x0a, data=AMBIENT, maxsend();     // Brightness: 0 = dim, f = brightest
   // Send "Burn Easy"
   address=0x04, data=91, maxsend();      // Send "S"
   address=0x03, data=79, maxsend();      // Send "E"
   address=0x02, data=15, maxsend();      // Send "t"
   address=0x01, data=0, maxsend();      // Send " "
   GetDigitsTemp(TempSetPoint);
   temp_msd_code = msd_code;      // temperature thousands
   temp_lsd2_code = lsd2_code;      // temperature hunsdreds
   temp_lsd1_code = lsd1_code;      // temperature tens
   temp_lsd_code = lsd_code;      // temperature ones
   delay_cycles(1);
   UpdateTempDisplay(TempSetPoint);
   while ((STEP_1_Pressed == True)||(STEP_2_Pressed == True))
   {
      delay_cycles(1);
   }
/*******************************************************************
// Adjust Temperature Setpoint
*******************************************************************/
   while (STEP_2_Pressed == False)         
   {         
      delay_cycles(1);
      while((UP_Pressed) && (TempSetPoint < 2000))
      {
         TempSetPoint++;
         delay_cycles(1);
         GetDigitsTemp(TempSetPoint);            // Get the Digits for the Preset Temp
         UpdateTempDisplay(TempSetPoint);
         if(Up_Held == True)
         {
            delay_ms(25);
         }
         else
         {
            delay_ms(250);
         }   
      }
      while((DOWN_Pressed) && (TempSetPoint > 500))
      {
         TempSetPoint--;
         delay_cycles(1);
         GetDigitsTemp(TempSetPoint);            // Get the Digits for the Preset Temp
         UpdateTempDisplay(TempSetPoint);
         if(Down_Held == True)
         {
            delay_ms(25);
         }
         else
         {
            delay_ms(250);
         }   
      }
   }
   delay_cycles(1);
   write_ext_eeprom(3,TempSetPoint);
   write_ext_eeprom(4,TempSetPoint>>8);
   delay_cycles(1);
   While (Step_2_Pressed == True)
   {
      delay_cycles(1);
   }
/*******************************************************************
// Adjust Fan Up Offset
*******************************************************************/
   while (STEP_2_Pressed == False)         
   {
       address=0x0a, data=AMBIENT, maxsend();     // Brightness: 0 = dim, f = brightest
      // Send "Burn Easy"
      address=0x04, data=71, maxsend();      // Send "F"
      address=0x03, data=119, maxsend();      // Send "A"
      address=0x02, data=21, maxsend();      // Send "n"
      address=0x01, data=62, maxsend();      // Send "U"
      GetDigitsTemp(FanUpOffset);
      temp_msd_code = msd_code;      // temperature thousands
      temp_lsd2_code = lsd2_code;      // temperature hunsdreds
      temp_lsd1_code = lsd1_code;      // temperature tens
      temp_lsd_code = lsd_code;      // temperature ones
      delay_cycles(1);
      UpdateTempDisplay(FanUpOffset);         
      delay_cycles(1);
      
      while((UP_Pressed) && (FanUpOffset < 200))
      {
         FanUpOffset++;
         delay_cycles(1);
         GetDigitsTemp(FanUpOffset);            // Get the Digits for the Preset Temp
         UpdateTempDisplay(FanUpOffset);
         if(Up_Held == True)
         {
            delay_ms(25);
         }
         else
         {
            delay_ms(250);
         }   
      }
      while((DOWN_Pressed) && (FanUpOffset > 50))
      {
         FanUpOffset--;
         delay_cycles(1);
         GetDigitsTemp(FanUpOffset);            // Get the Digits for the Preset Temp
         UpdateTempDisplay(FanUpOffset);
         if(Down_Held == True)
         {
            delay_ms(25);
         }
         else
         {
            delay_ms(250);
         }   
      }
   }
   delay_cycles(1);
   write_ext_eeprom(5,FanUpOffset);
   write_ext_eeprom(6,FanUpOffset>>8);
   delay_cycles(1);
   While (Step_2_Pressed == True)
   {
      delay_cycles(1);
      StartTimer = 0;
   }
/*******************************************************************
// Adjust Fan Down Offset
*******************************************************************/
   while (STEP_2_Pressed == False)         
   {
      FanDownChange = True;
       address=0x0a, data=AMBIENT, maxsend();     // Brightness: 0 = dim, f = brightest
      // Send "Burn Easy"
      address=0x04, data=71, maxsend();      // Send "F"
      address=0x03, data=119, maxsend();      // Send "A"
      address=0x02, data=21, maxsend();      // Send "n"
      address=0x01, data=61, maxsend();      // Send "d"
      GetDigitsTemp(FanDownOffset);
      temp_msd_code = msd_code;      // temperature thousands
      temp_lsd2_code = lsd2_code;      // temperature hunsdreds
      temp_lsd1_code = lsd1_code;      // temperature tens
      temp_lsd_code = lsd_code;      // temperature ones
      delay_cycles(1);
      UpdateTempDisplay(FanDownOffset);         
      delay_cycles(1);

      if(FanDownOffset > 100)
      {
         temp_msd_code = 1;         // Send "-"
      }
      else
      {
         temp_msd_code = 0;         // Send " "
         temp_lsd2_code = 1;         // Send "-"
      }   
      UpdateTempDisplay(FanDownOffset);
      delay_cycles(1);
      
      while((UP_Pressed) && (FanDownOffset < 200))
      {
         FanDownOffset++;
         delay_cycles(1);
         GetDigitsTemp(FanDownOffset);            // Get the Digits for the Preset Temp
         UpdateTempDisplay(FanDownOffset);
         if(Up_Held == True)
         {
            delay_ms(25);
         }
         else
         {
            delay_ms(250);
         }   
      }
      while((DOWN_Pressed) && (FanDownOffset > 50))
      {
         FanDownOffset--;
         delay_cycles(1);
         GetDigitsTemp(FanDownOffset);            // Get the Digits for the Preset Temp
         UpdateTempDisplay(FanDownOffset);
         if(Down_Held == True)
         {
            delay_ms(25);
         }
         else
         {
            delay_ms(250);
         }   
      }
   }
   delay_cycles(1);
   write_ext_eeprom(7,FanDownOffset);
   write_ext_eeprom(8,FanDownOffset>>8);
   delay_cycles(1);
   FanDownChange = False;   
   delay_cycles(1);
   While (Step_2_Pressed == True)
   {
      delay_cycles(1);
      StartTimer = 0;
   }
/*******************************************************************
// Adjust Fuel Offset
*******************************************************************/
   while (STEP_2_Pressed == False)         
   {
      FuelChange = True;
       address=0x0a, data=AMBIENT, maxsend();     // Brightness: 0 = dim, f = brightest
      // Send "Burn Easy"
      address=0x04, data=71, maxsend();      // Send "F"
      address=0x03, data=62, maxsend();      // Send "U"
      address=0x02, data=79, maxsend();      // Send "E"
      address=0x01, data=14, maxsend();      // Send "L"
      GetDigitsTemp(FuelOffset);
      temp_msd_code = msd_code;      // temperature thousands
      temp_lsd2_code = lsd2_code;      // temperature hunsdreds
      temp_lsd1_code = lsd1_code;      // temperature tens
      temp_lsd_code = lsd_code;      // temperature ones
      delay_cycles(1);
      if(FuelOffset > 100)
      {
         temp_msd_code = 1;         // Send "-"
      }
      else
      {
         temp_msd_code = 0;         // Send " "
         temp_lsd2_code = 1;         // Send "-"
      }   
      UpdateTempDisplay(FuelOffset);
      delay_cycles(1);
      
      while((UP_Pressed) && (FuelOffset < 200))
      {
         FuelOffset++;
         delay_cycles(1);
         GetDigitsTemp(FuelOffset);            // Get the Digits for the Preset Temp
         UpdateTempDisplay(FuelOffset);
         if(Up_Held == True)
         {
            delay_ms(25);
         }
         else
         {
            delay_ms(250);
         }   
      }
      while((DOWN_Pressed) && (FuelOffset > 50))
      {
         FuelOffset--;
         delay_cycles(1);
         GetDigitsTemp(FuelOffset);            // Get the Digits for the Preset Temp
         UpdateTempDisplay(FuelOffset);
         if(Down_Held == True)
         {
            delay_ms(25);
         }
         else
         {
            delay_ms(250);
         }   
      }
   }
   delay_cycles(1);
   write_ext_eeprom(9,FuelOffset);
   write_ext_eeprom(10,FuelOffset>>8);
   delay_cycles(1);
   FuelChange = False;   
   delay_cycles(1);
   While (Step_2_Pressed == True)
   {
      delay_cycles(1);
      StartTimer = 0;
   }
/*******************************************************************
// Adjust Cool Down Set point
*******************************************************************/
   while (STEP_2_Pressed == False)         
   {
       address=0x0a, data=AMBIENT, maxsend();     // Brightness: 0 = dim, f = brightest
      delay_cycles(1);
      address=0x04, data=78, maxsend();      // Send "C"
      address=0x03, data=126, maxsend();      // Send "O"
      address=0x02, data=126, maxsend();      // Send "O"
      address=0x01, data=14, maxsend();      // Send "L"
      GetDigitsTemp(CoolSet);
      temp_msd_code = msd_code;      // temperature thousands
      temp_lsd2_code = lsd2_code;      // temperature hunsdreds
      temp_lsd1_code = lsd1_code;      // temperature tens
      temp_lsd_code = lsd_code;      // temperature ones
      delay_cycles(1);
      UpdateTempDisplay(CoolSet);         
      delay_cycles(1);
      
      while((UP_Pressed) && (CoolSet < TempSetPoint))
      {
         CoolSet++;
         delay_cycles(1);
         GetDigitsTemp(CoolSet);            // Get the Digits for the Preset Temp
         UpdateTempDisplay(CoolSet);
         if(Up_Held == True)
         {
            delay_ms(25);
         }
         else
         {
            delay_ms(250);
         }   
      }
      while((DOWN_Pressed) && (CoolSet > 34))
      {
         CoolSet--;
         delay_cycles(1);
         GetDigitsTemp(CoolSet);            // Get the Digits for the Preset Temp
         UpdateTempDisplay(CoolSet);
         if(Down_Held == True)
         {
            delay_ms(25);
         }
         else
         {
            delay_ms(250);
         }   
      }
   }
   delay_cycles(1);
   write_ext_eeprom(11,CoolSet);
   write_ext_eeprom(12,CoolSet>>8);
   delay_cycles(1);

    address=0x0a, data=AMBIENT, maxsend();     // Brightness: 0 = dim, f = brightest
   // Send "Burn Easy"
   address=0x08, data=127, maxsend();      // Send "B"
   address=0x07, data=28, maxsend();      // Send "u"
   address=0x06, data=5, maxsend();      // Send "r"
   address=0x05, data=21, maxsend();      // Send "n"
   address=0x04, data=79, maxsend();      // Send "E"
   address=0x03, data=119, maxsend();      // Send "A"
   address=0x02, data=91, maxsend();      // Send "S"
   address=0x01, data=59, maxsend();      // Send "y"
}
/******************************************************************************************
// Display Probe Temperature
******************************************************************************************/
void DisplayProbeTemp(int16 PassedTemp)
{
   if (LowTemp == True)
   {
      delay_cycles(1);
      address=0x08, data=0, maxsend();      // Send " "
      address=0x07, data=0, maxsend();      // Send " "
      address=0x06, data=14, maxsend();      // Send "L"
      address=0x05, data=29, maxsend();      // Send "0"
      delay_cycles(1);
   }
   else
   {
      delay_cycles(1);
      GetDigitsTemp(PassedTemp);
      temp_msd_code = msd_code;      // temperature thousands
      temp_lsd2_code = lsd2_code;      // temperature hunsdreds
      temp_lsd1_code = lsd1_code;      // temperature tens
      temp_lsd_code = lsd_code;      // temperature ones
      UpdateTempDisplay(Probe_Temp_F);
   }
}
void PreloadSetPoints()
{
   delay_cycles(1);
   hour_timer = 2;
   min_timer = 0;
   CountDownTimer=make16(hour_timer, min_timer);
   write_ext_eeprom(1,CountDownTimer);
   write_ext_eeprom(2,CountDownTimer>>8);
   delay_cycles(1);
   TempSetPoint = 1400;
   write_ext_eeprom(3,TempSetPoint);
   write_ext_eeprom(4,TempSetPoint>>8);
   delay_cycles(1);
   FanUpOffSet = 100;
   write_ext_eeprom(5,FanUpOffset);
   write_ext_eeprom(6,FanUpOffset>>8);
   FanDownOffSet = 25;
   write_ext_eeprom(7,FanDownOffset);
   write_ext_eeprom(8,FanDownOffset>>8);
   delay_cycles(1);
   FuelOffSet = 75;
   write_ext_eeprom(9,FuelOffset);
   write_ext_eeprom(10,FuelOffset>>8);
   delay_cycles(1);
   CoolSet = 350;
   write_ext_eeprom(11,CoolSet);
   write_ext_eeprom(12,CoolSet>>8);
   delay_cycles(1);
}
void ReadStoredSetpoints()
{
   delay_cycles(1);
   data1 = read_ext_eeprom(1);
   data2 = read_ext_eeprom(2);
   data2 = data2<<8;
   CountDownTimer = data2+data1;
   delay_cycles(1);
   data1 = read_ext_eeprom(3);
   data2 = read_ext_eeprom(4);
   data2 = data2<<8;
   TempSetPoint = data2+data1;
   delay_cycles(1);
   data1 = read_ext_eeprom(5);
   data2 = read_ext_eeprom(6);
   data2 = data2<<8;
   FanUpOffset = data2+data1;
   delay_cycles(1);
   data1 = read_ext_eeprom(7);
   data2 = read_ext_eeprom(8);
   data2 = data2<<8;
   FanDownOffset = data2+data1;
   delay_cycles(1);
   data1 = read_ext_eeprom(9);
   data2 = read_ext_eeprom(10);
   data2 = data2<<8;
   FuelOffset = data2+data1;
   delay_cycles(1);
   data1 = read_ext_eeprom(11);
   data2 = read_ext_eeprom(12);
   data2 = data2<<8;
   CoolSet = data2+data1;
   delay_cycles(1);      
}
/*******************************************************************************
// Main Program starts here
*******************************************************************************/
void main()
{
   SETUP_CCP1(CCP_OFF);
   init_ext_eeprom();
   output_high(DISP);
   output_high(TEMP);
    maxsetup();
   address=0x01, data=127, maxsend();  // send "8"
   address=0x02, data=112, maxsend();  // send "7"
   address=0x03, data=95, maxsend();   // send "6"
   address=0x04, data=91, maxsend();   // send "5"
   address=0x05, data=51, maxsend();   // send "4"
   address=0x06, data=121, maxsend();   // send "3"
   address=0x07, data=109, maxsend();   // send "2"
   address=0x08, data=48, maxsend();   // send "1"
   delay_ms(500);
   delay_cycles(1);
//   output_high(DISP);
//   output_high(TEMP);
   SETUP_ADC_PORTS(sAN0 | sAN1);
   SETUP_ADC(adc_clock_div_8);
//    maxsetup();
   ten_ms_timer = 0;      // milisecond timer
   tenths_timer = 0;   // tenth of a second timer
   sec_timer = 0;      // seconds timer
   min_timer = 0;      // minute timer
   hour_timer = 0;      // hour timer
   SETUP_TIMER_2(T2_DIV_BY_4,249,10);   // 10ms interrupts
   enable_interrupts(INT_TIMER2);
   enable_interrupts(GLOBAL);
   StatusBits1 = 0;
   StatusBits2 = 0;
   ButtonsPressed = 0;
//   hour_timer = 00;
//   min_timer = 2;
   sec_timer = 60;
   ten_ms_timer = 10;
   TimerDone = True;
   TempSetPoint = 1400;
   FanUpOffset = 100;
   FuelOffset = 75;
   FanOnTimer = 0;
   FuelOnTimer = 0;
   StartTimer = 0;
   StartTemp = 0;
   HeartBeatTimer = 0;
   CountDownTimer=make16(hour_timer, min_timer); // Puts hour in highbyte and minute in low byte
   delay_ms(100);
/************************************************************************************************
// Preload setpoints if Cali is Jumpered
************************************************************************************************/
   if(input_state(CALI_IN) == Low) // CALI_IN is jumpered so preload timers and eeprom
   {
      PreloadSetPoints();
   }

/************************************************************************************************
// Read Stored setpoints
************************************************************************************************/
   ReadStoredSetpoints();
   delay_cycles(1);

/***********************************************************************************************
// Temperature Change Requested at startup by holding down both Step Buttons at startup
***********************************************************************************************/
   if ((STEP_1_Pressed == True) && (STEP_2_Pressed == True))
   {
      delay_cycles(1);
      read_analog();
      TempChange();      // Temperature Change Routine
   }

/***********************************************************************************************
// Beginning of main program. Initial start sequence
***********************************************************************************************/
      while (STEP_1_Pressed == False)
      {
         readMAX();
         if(tempFault() == 0)
         {
            if(StartTimer < 20)
            {
               read_analog();
                address=0x0a, data=AMBIENT, maxsend();     // Brightness: 0 = dim, f = brightest
               // Send "Burn Easy"
               address=0x08, data=127, maxsend();      // Send "B"
               address=0x07, data=28, maxsend();      // Send "u"
               address=0x06, data=5, maxsend();      // Send "r"
               address=0x05, data=21, maxsend();      // Send "n"
               address=0x04, data=79, maxsend();      // Send "E"
               address=0x03, data=119, maxsend();      // Send "A"
               address=0x02, data=91, maxsend();      // Send "S"
               address=0x01, data=59, maxsend();      // Send "y"
            }
            else
            {
               address=0x01, data=0, maxsend();
               address=0x02, data=0, maxsend();
               address=0x03, data=0, maxsend();
               address=0x04, data=0, maxsend();
               address=0x05, data=0, maxsend();
               address=0x06, data=0, maxsend();
               address=0x07, data=0, maxsend();
               address=0x08, data=0, maxsend();
            }
         }
         if (tempFault() != 0)         // Send "Prob FAIL"
         {
            address=0x08, data=103, maxsend();      // Send "P"
            address=0x07, data=5, maxsend();      // Send "r"
            address=0x06, data=29, maxsend();      // Send "o"
            address=0x05, data=31, maxsend();      // Send "b"
            address=0x04, data=71, maxsend();      // Send "F"
            address=0x03, data=119, maxsend();      // Send "A"
            address=0x02, data=48, maxsend();      // Send "I"
            address=0x01, data=14, maxsend();      // Send "L"
            delay_ms(500);
            // Send "BLANK DISPLAY"
            address=0x01, data=0, maxsend();
            address=0x02, data=0, maxsend();
            address=0x03, data=0, maxsend();
            address=0x04, data=0, maxsend();
            address=0x05, data=0, maxsend();
            address=0x06, data=0, maxsend();
            address=0x07, data=0, maxsend();
            address=0x08, data=0, maxsend();
            delay_ms(500);
            ProbeFailed = True;
            output_low(FAN_RY);
            output_low(FUEL_RY);
         }
      }

      if ((StartTimer >= 20)&&(STEP_1_Pressed == True))
      {
         readMAX();
         read_analog();
          address=0x0a, data=AMBIENT, maxsend();     // Brightness: 0 = dim, f = brightest
         // Send "Burn Easy"
         address=0x08, data=127, maxsend();      // Send "B"
         address=0x07, data=28, maxsend();      // Send "u"
         address=0x06, data=5, maxsend();      // Send "r"
         address=0x05, data=21, maxsend();      // Send "n"
         address=0x04, data=79, maxsend();      // Send "E"
         address=0x03, data=119, maxsend();      // Send "A"
         address=0x02, data=91, maxsend();      // Send "S"
         address=0x01, data=59, maxsend();      // Send "y"
         while (STEP_1_Pressed == True)
         {
            delay_cycles(1);
         }
         while (Step_1_Pressed == False)
         {
            read_analog();
             address=0x0a, data=AMBIENT, maxsend();     // Brightness: 0 = dim, f = brightest
            delay_cycles(1);
         }      
      }

/************************************************************************************************
// Main Program main loop after startup sequence
************************************************************************************************/
   while(TRUE)                        //   Begin main loop after inital setup
   {
       readMAX();
      while (tempFault() != 0)         // Send "Prob FAIL"
      {
         address=0x08, data=103, maxsend();      // Send "P"
         address=0x07, data=5, maxsend();      // Send "r"
         address=0x06, data=29, maxsend();      // Send "o"
         address=0x05, data=31, maxsend();      // Send "b"
         address=0x04, data=71, maxsend();      // Send "F"
         address=0x03, data=119, maxsend();      // Send "A"
         address=0x02, data=48, maxsend();      // Send "I"
         address=0x01, data=14, maxsend();      // Send "L"
         delay_ms(500);
         if(STEP_2_PRESSED == True)
         {
            reset_cpu();
         }
         // Send "BLANK DISPLAY"
         address=0x01, data=0, maxsend();
         address=0x02, data=0, maxsend();
         address=0x03, data=0, maxsend();
         address=0x04, data=0, maxsend();
         address=0x05, data=0, maxsend();
         address=0x06, data=0, maxsend();
         address=0x07, data=0, maxsend();
         address=0x08, data=0, maxsend();
         delay_ms(500);
         ProbeFailed = True;
         output_low(FAN_RY);
         output_low(FUEL_RY);
         if(STEP_2_PRESSED == True)
         {
            reset_cpu();
         }
      }
//      if (tempFault() == 0)         //   Probe is good
//      {      
//         ProbeFailed = False;
//      }
      delay_cycles(1);

/*********************************************************************************************
// Set Timer Preset
*********************************************************************************************/

      if((STEP_1_Pressed == True)&&(TimerDone==True) && (STEP_2_Pressed == False))
      {
         address=0x08, data=91, maxsend();      // Send "S"
         address=0x07, data=79, maxsend();      // Send "E"
         address=0x06, data=15, maxsend();      // Send "t"
         address=0x05, data=0, maxsend();      // Send " "
         address=0x04, data=0, maxsend();      // Send " "
         address=0x03, data=0, maxsend();      // Send " "
         address=0x02, data=0, maxsend();      // Send " "
         address=0x01, data=0, maxsend();      // Send " "

         delay_cycles(1);
//         TimerDone = False;
//         ColonOn == 128;
         GetDigitsTimer(CountDownTimer);            // Get the Digits for the Timer
         hour_timer = make8(CountDownTimer, 1);
         min_timer = make8(CountDownTimer, 0);
         UpdateTimeDisplay();
         delay_ms(250);
         while (STEP_2_Pressed == False)         
         {         
            delay_cycles(1);
            while((UP_Pressed) && (hour_timer < 24))
            {
               delay_cycles(1);
               if (min_timer == 0)
               {
                  delay_cycles(1);
                  min_timer = 30;
                  CountDownTimer=make16(hour_timer, min_timer);
               }
               else
               {
                  delay_cycles(1);
                  min_timer = 0;
                  hour_timer = hour_timer + 1;
                  CountDownTimer=make16(hour_timer, min_timer);
               }
               delay_cycles(1);
               GetDigitsTimer(CountDownTimer);            // Get the Digits for the Timer
               UpdateTimeDisplay();
               delay_ms(250);
            }
            while((DOWN_Pressed) && (hour_timer > 0))
            {
               delay_cycles(1);
               if (min_timer == 30)
               {
                  delay_cycles(1);
                  min_timer = 0;
                  CountDownTimer=make16(hour_timer, min_timer);
               }
               else
               {
                  delay_cycles(1);
                  min_timer = 30;
                  hour_timer = hour_timer - 1;
                  CountDownTimer=make16(hour_timer, min_timer);
               }
               delay_cycles(1);
               GetDigitsTimer(CountDownTimer);            // Get the Digits for the Timer
               UpdateTimeDisplay();
               delay_ms(250);
            }
         }
         delay_cycles(1);
         write_ext_eeprom(1,CountDownTimer);               // Store new CountDownTimer Value in eeProm
         write_ext_eeprom(2,CountDownTimer>>8);
         delay_cycles(1);
         while(Step_2_Pressed == True)
         {
            delay_cycles(1);
         }      
         TimerDone = False;                     
      }
/**********************************************************************************
// Look for Pushbutton 1 pressed to Pause or Reset
**********************************************************************************/
      if((TimerDone == False)&&(CheckPause == True))
      {
         CheckPause = False;
         if ((Step_2_Pressed == True)&&(TimerPaused == False))
         {
            ColonOn = 128;
            delay_cycles(1);
            GetDigitsTimer(CountDownTimer);
            UpdateTimeDisplay();
            TimerPaused = True;
            output_low(FAN_RY);
            output_low(FUEL_RY);
         }
      }

/*********************************************************************************
// Update Temperature when timer paused
*********************************************************************************/

      if ((TimerPaused == True)&&(PausedTemp == True))
      {
         PausedTemp = False;
         readExtTemp();
         DisplayProbeTemp(Probe_Temp_F);
      }
/*********************************************************************************
// Run main furnace control program
*********************************************************************************/

      if (LoadTimeDisplay == True)
      {
         delay_cycles(1);
         if (TimerDone == False)
         {
            GetDigitsTimer(CountDownTimer);            // Get the Digits for the Timer
            UpdateTimeDisplay();
            LoadTimeDisplay = False;
         }
         read_analog();
          address=0x0a, data=AMBIENT, maxsend();     // Brightness: 0 = dim, f = brightest
         delay_cycles(1);
/********************************************************************************
// Use this code to read the internal temperature
********************************************************************************/
//         readIntTemp();               // Get the Chips Temperature
//         GetDigitsTemp(Chip_Temp_F);
//         temp_msd_code = msd_code;      // temperature thousands
//         temp_lsd2_code = lsd2_code;      // temperature hunsdreds
//         temp_lsd1_code = lsd1_code;      // temperature tens
//         temp_lsd_code = lsd_code;      // temperature ones
//         delay_cycles(1);

         delay_cycles(1);
/**********************************************************************************
// Display Probe Temperature
**********************************************************************************/
         readExtTemp();
         DisplayProbeTemp(Probe_Temp_F);

/**********************************************************************************
// Fan and Burner Control
**********************************************************************************/
         if((TimerDone == False)&&(TimerPaused == False))
         {
            delay_cycles(1);
            if(Probe_Temp_F < TempSetPoint)
            {
               if(FanStart == False)
               {
                  FanStart = True;
               }
               delay_cycles(1);
               output_high(FAN_RY);
            }
            if(((input_state(FUEL_RY)) == False)&&(FuelStart == True) && (Probe_Temp_F < (TempSetPoint - FuelOffset)))
            {
               delay_cycles(1);
               output_high(FUEL_RY);
               FuelOnTimer = 0;
//               StartTemp = Probe_Temp_F;
            }
            if(Probe_Temp_F >= (TempSetPoint))
            {
               delay_cycles(1);
               output_low(FUEL_RY);
            }
            if(Probe_Temp_F >= (TempSetPoint + FanUpOffset)&&(input_state(HIGH_LED)==False))
            {
               delay_cycles(1);
               output_low(FAN_RY);
               output_high(HIGH_LED);
            }
            if(Probe_Temp_F <= (TempSetPoint + FanUpOffset - FanDownOffset))
            {
               delay_cycles(1);
               output_high(Fan_RY);
               output_low(HIGH_LED);
            }
            if((FuelOnTimer >=10)&&(TempReached == False)&&(Probe_Temp_Signed > (StartTemp + 10)))
            {
               delay_cycles(1);
               TempReached = True;
            }
            if((input_state(FAN_RY))&&(FanOnTimer>=100))
            {
               delay_cycles(1);
               if(FuelStart == False)
               {
                  output_high(FUEL_RY);
                  StartTemp = Probe_Temp_Signed;   // Initial temp when Fuel Starts
                  FuelStart = True;
                  FuelOnTimer = 0;
               }
               if((FuelOnTimer >= 300)&&(TempReached == False)&&(Probe_Temp_Signed <= (StartTemp +10)))   // Temp rise fault
               {
                  delay_cycles(1);
                  while (STEP_2_PRESSED == False)
                  {
                     output_low(FUEL_RY);
                     address=0x08, data=0, maxsend();      // Send " "
                     address=0x07, data=21, maxsend();      // Send "n"
                     address=0x06, data=29, maxsend();      // Send "o"
                     address=0x05, data=0, maxsend();      // Send " "
                     address=0x04, data=71, maxsend();      // Send "F"
                     address=0x03, data=62, maxsend();      // Send "U"
                     address=0x02, data=79, maxsend();      // Send "E"
                     address=0x01, data=14, maxsend();      // Send "L"
                  }
                     delay_cycles(1);
                     reset_cpu();
               }
            }
         }   
               

/**********************************************************************************
// Display Timer Done when countdown is fhinished
**********************************************************************************/
         if (TimerDone == True)
         {
            address=0x08, data=127, maxsend();      // Send "B"
            address=0x07, data=28, maxsend();      // Send "u"
            address=0x06, data=5, maxsend();      // Send "r"
            address=0x05, data=21, maxsend();      // Send "n"
            address=0x04, data=61, maxsend();      // Send "d"
            address=0x03, data=29, maxsend();      // Send "o"
            address=0x02, data=21, maxsend();      // Send "n"
            address=0x01, data=79, maxsend();      // Send "E"
            LoadTimeDisplay = False;
            output_low(FUEL_RY);
            output_high(FAN_RY);
            while ((TimerDone == True)&&(Probe_Temp_F >= CoolSet))
            {
               delay_cycles(1);
               delay_ms(500);
               address=0x08, data=127, maxsend();      // Send "B"
               address=0x07, data=28, maxsend();      // Send "u"
               address=0x06, data=5, maxsend();      // Send "r"
               address=0x05, data=21, maxsend();      // Send "n"
               address=0x04, data=61, maxsend();      // Send "d"
               address=0x03, data=29, maxsend();      // Send "o"
               address=0x02, data=21, maxsend();      // Send "n"
               address=0x01, data=79, maxsend();      // Send "E"
               delay_ms(500);
               readMAX();
               readExtTemp();

               if(tempFault() != 0)         // Send "Prob FAIL"
               {
                  address=0x08, data=103, maxsend();      // Send "P"
                  address=0x07, data=5, maxsend();      // Send "r"
                  address=0x06, data=29, maxsend();      // Send "o"
                  address=0x05, data=31, maxsend();      // Send "b"
                  address=0x04, data=71, maxsend();      // Send "F"
                  address=0x03, data=119, maxsend();      // Send "A"
                  address=0x02, data=48, maxsend();      // Send "I"
                  address=0x01, data=14, maxsend();      // Send "L"
                  output_low(FAN_RY);
                  output_low(HIGH_LED);
                  if(STEP_2_Pressed == TRUE) reset_cpu();
               }
               else
               {
                  output_high(FAN_RY);
                  address=0x04, data=78, maxsend();      // Send "C"
                  address=0x03, data=126, maxsend();      // Send "O"
                  address=0x02, data=126, maxsend();      // Send "O"
                  address=0x01, data=14, maxsend();      // Send "L"
                  delay_cycles(1);
                  GetDigitsTemp(Probe_Temp_F);
                  temp_msd_code = msd_code;      // temperature thousands
                  temp_lsd2_code = lsd2_code;      // temperature hunsdreds
                  temp_lsd1_code = lsd1_code;      // temperature tens
                  temp_lsd_code = lsd_code;      // temperature ones
                  UpdateTempDisplay(Probe_Temp_F);
               }
               delay_ms(500);
            }
            address=0x01, data=0, maxsend();
            address=0x02, data=0, maxsend();
            address=0x03, data=0, maxsend();
            address=0x04, data=0, maxsend();
            address=0x05, data=0, maxsend();
            address=0x06, data=0, maxsend();
            address=0x07, data=0, maxsend();
            address=0x08, data=0, maxsend();
            output_low(FUEL_RY);
            output_low(FAN_RY);
            output_low(HIGH_LED);
            while (STEP_1_PRESSED == False)
            {
               delay_cycles(1);
            }
            reset_cpu();
         }
      }
      delay_cycles(1);
   }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Thu Mar 22, 2018 2:38 pm     Reply with quote

I'd not expect to be able to change the supported transfer length like this.
Leave both #use SPI setups using 32bit, and specify the number of bits to transfer in the individual spi_xfer commands.
so spi_xfer(STREAM, data, 8); for the device wanting 8bit transfers and then 32 for the device wanting 32bit transfers.
edbfmi1



Joined: 18 Jul 2006
Posts: 94

View user's profile Send private message

PostPosted: Thu Mar 22, 2018 3:34 pm     Reply with quote

Thanks for the quick response!

I made the following changes. But still do not get the display to act properly.
Code:

#use spi(SPI1, MASTER, MODE=0, bits=32, stream=MAX31855)
#use spi(SPI1, MASTER, MODE=0, bits=32, stream=MAX7219)


Code:

/**********************************************************************************
// Send Update Display, MAX7219
**********************************************************************************/
void maxsend()                     // send routine for max7219 to update display
{
   spi_xfer(MAX7219,0,8);             //switches the stream to mode 0
   delay_us(10);     
   output_low(DISP);
   delay_us(10);                     
   spi_xfer(MAX7219,address,8);         //send address
//   delay_us(10);     
   spi_xfer(MAX7219,data,8);            //send data
//   delay_us(10);
   output_high(DISP);
//   delay_us(10);
}


Code:

/*******************************************************************************
//Read SPI data From MAX31855
*******************************************************************************/ 
void readMAX()
{
   int32 MAXread;
   spi_xfer(MAX31855,0,32);                //switches the stream to mode 0    
   output_low(TEMP);
   delay_us(10);
   MAXread=spi_xfer(MAX31855,0,32);
//   delay_us(10);
   output_high(TEMP);
//   delay_us(10);
   TempByte3=MAXread>>24 & 0xff;
   TempByte2=MAXread>>16 & 0xff;
   TempByte1=MAXread>>8 & 0xff;
   TempByte0=MAXread & 0xff;
}
edbfmi1



Joined: 18 Jul 2006
Posts: 94

View user's profile Send private message

PostPosted: Thu Mar 22, 2018 3:45 pm     Reply with quote

I noticed in the Errata sheet for the PIC16F1518 that it says the following.
Could this be the problem? I really don't know how to check for the error or implement the workaround.

Quote:
6.1 SPI Master mode
When the MSSP is used in SPI Master mode and
the CKE bit is clear (CKE = 0), the Buffer Full (BF)
bit and the MSSP Interrupt Flag (SSPIF) bit
becomes set half an SCK cycle early. If the user
software immediately reacts to either of the bits
being set, a write collision may occur as indicated
by the WCOL bit being set.
Work around
To avoid a write collision one of the following
methods should be used:
Method 1: Add a software delay of one SCK
period after detecting the
completed transfer (the BF bit or
SSPIF bit becomes set) and prior
to writing to the SSPBUF register.
Verify the WCOL bit is clear after
writing to SSPBUF. If the WCOL
bit is set, clear the bit in software
and rewrite the SSPBUF register.
Method 2: As part of the MSSP initialization
procedure, set the CKE bit
(CKE = 1).
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Thu Mar 22, 2018 3:46 pm     Reply with quote

OK.
The fact it works with some units suggests something like a timing issue. I've seen displays where here is a wide variation in start-up times needed between different units. The SPI bus itself ought to be timing independant, but things like the delays needed between commands may differ. Check the data sheet, and in particular look at the 'worst case' timings needed. Does the code meet all of these?.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group