/* thermo-manipulator_NTC_ino */


/* --- Temperature calculation  --- */
float temperatureNTC( unsigned int ADvalue );

/* --- serial shift 3+4 digit seven-segment display  --- */
#define SDI_PIN  4
#define SCLK_PIN 3
#define LOAD_PIN 2
#define DIGITS   7
unsigned char sevseg_array[ DIGITS ];
void sevseg_temperature(unsigned char *, unsigned int);
void sevseg_setChange(unsigned char *, signed int);
void ShiftOut_array(unsigned char *, unsigned char length);

/* --- 7-segment display lookup table  --- */
 const unsigned char NUMBERS[] = {
  // "0123465789 -" for active Low display
   0x03,  // 0000 0011  "0"
   0x9F,  // 1001 1111  "1"
   0x25,  // 0010 0101  "2"
   0x0D,  // 0000 1101  "3"
   0x99,  // 1001 1001  "4"
   0x49,  // 0100 1001  "5"
   0x41,  // 0100 0001  "6"
   0x1F,  // 0001 1111  "7"
   0x01,  // 0000 0001  "8"
   0x19,  // 0001 1001  "9"
   0xFF,  // 1111 1111  "Blank"
   0xFD   //  1111 1101 "Minus"
  };


/* --- Up/Dwn buttons --- */
void init_updwn( void);
float Change = 0.0;
signed int svalue = 0;

/* --- PWM output  --- */
void init_PWM( void );
// PB1, DDRB, OC1A, (D09) 
#define MAX_PWM_VALUE 1023  // resolution 10 bit pwm (16 bit max)



void setup() {

  Serial.begin(9600);
  pinMode(LOAD_PIN, OUTPUT);
  pinMode(SDI_PIN, OUTPUT);
  pinMode(SCLK_PIN, OUTPUT);
  init_updwn( );
  init_PWM( );

  sevseg_setChange( sevseg_array, 0 ); 

  delay(500);
}


void loop() {

   ShiftOut_array( sevseg_array, DIGITS );

  unsigned int ADvalueFWD = analogRead(A0);
  unsigned int ADvalueRET = analogRead(A1);

  float celsiusFWD, celsiusRET;


  float k, m;
  float GradientDecrease, GradientIncrease, Offset, Vset, PWM_float;

  float t;
  unsigned int pwm, uvalue;
  
  celsiusFWD = temperatureNTC( ADvalueFWD );
  celsiusRET = temperatureNTC( ADvalueRET );

  
  Serial.print("FWD Temperature: ");
  Serial.print(celsiusFWD);
  Serial.print(" ℃");
 
  Serial.print("  (REW Temperature: ");
  Serial.print(celsiusRET);
  Serial.println(" ℃ )");


// present FWD thermometer temperature value
      t = celsiusFWD;
      t *= 10.0;  
      t += 0.5;       // round
      uvalue = (unsigned int) t;  // keep integer part

  sevseg_temperature( sevseg_array, uvalue );


// GradientIncrease
k = (0.6-1.013)/(76.8-24.6);
m=1.013-k*24.6;
GradientIncrease= k*celsiusFWD + m;

// GradientDecrease
k=(-0.68 - -0.875)/(76.8-24.6);
m=-0.875-k*24.6;
GradientDecrease= -(k*celsiusFWD + m);

// Offset
k = (0.308-0.255)/(76.8-24.6);
m = 0.255-k*24.6;
Offset = k*celsiusFWD + m;

if(Change < 0) Vset=Offset+Change*GradientDecrease;
else Vset=Offset+Change*GradientIncrease;


  Serial.print("Change: ");
  Serial.print(Change);
  Serial.print(" ℃");

  Serial.print("   Vset: ");
  Serial.print(Vset);
  Serial.println(" V");

// PWM 10 bit
k=1024.0/4.48;
m=1023.0-k*2.24;

PWM_float=k*Vset+m;
pwm =(int) PWM_float;


     if( pwm > 1023 ) pwm = 1023;     
     OCR1A = pwm & 0x03FF; // Set a 10 bit PWM value

  Serial.print("PWM value: ");
  Serial.print( pwm );
  Serial.println( );
  Serial.println( );



     // readUp Button
    if( ( PINC & ( 1 << PC3 )) == 0 ) 
     { 
       svalue += 5;
       if( svalue > 250 ) svalue = 250;       
       sevseg_setChange( sevseg_array, svalue );
       ShiftOut_array( sevseg_array, DIGITS ); 
       Change = (float) svalue;
       Change /= 100.0;    
       while( ( PINC & ( 1 << PC3 )) == 0 ) /* do nothing */ ; // wait for button release
     }

    
    // read Dwn Button
    if( ( PINC & ( 1 << PC2 )) == 0 )
     { 
       svalue -= 5;
       if( svalue < -250 ) svalue = -250;       
       sevseg_setChange( sevseg_array, svalue ); 
       ShiftOut_array( sevseg_array, DIGITS );
       Change = (float) svalue;
       Change /= 100.0;    
       while( ( PINC & ( 1 << PC2 )) == 0 ) /* do nothing */ ; // wait for button release
     }


  delay(500);
}







/* *********************************** */
/*            FUNCTIONS                */
/* *********************************** */

/* ------------------------ */
/*  Temperature conversion  */
/* ------------------------ */

float temperatureNTC( unsigned int ADvalue ) //  using Steinhart-Hart 
{
const float BETA = 3950; 
// should match the Beta Coefficient of the thermistor

float celsius = 1 / (log(1 / (1023. / ADvalue - 1)) / BETA + 1.0 / 298.15) - 273.15;
if(celsius < 0) celsius = 0;
return celsius;
}


/* ----------------------------- */
/*  Shiftregister 7-seg display  */
/* ----------------------------- */

void sevseg_temperature(unsigned char sevseg_array[], unsigned int temperature)
{
  unsigned char data;
  unsigned int temp;
  
  temp = temperature % 10;  // x--
  data = (unsigned char) temp;
  data = NUMBERS[data];
  // data &= 0xFE;  // insert decimal point x.--
  sevseg_array[4] = data;

  temperature = temperature / 10; 
  temp = temperature % 10;   // -x-
  data = (unsigned char) temp;
  data = NUMBERS[data];
  data &= 0xFE;  // insert decimal point -x.-
  sevseg_array[5] = data; 

  temperature = temperature / 10; 
  temp = temperature % 10;  // --x
  data = (unsigned char) temp;
  data = NUMBERS[data];
  // data &= 0xFE;  // insert decimal point --x.
  sevseg_array[6] = data;
}


void sevseg_setChange(unsigned char sevseg_array[], signed int number)
{ /* sign, 3 digits, 2 decimals */
  unsigned char data;
  unsigned int num;
  unsigned char sign = 0;
  if(number <0 ){number=-number; sign =1; }
  

  num = number % 10;
  data = (unsigned char) num;
  data = NUMBERS[data];
  sevseg_array[0] = data;
  

  number = number / 10; 
  num = number % 10;
  data = (unsigned char) num;
  data = NUMBERS[data];
 // data &= 0xFE;  // insert decimal point  
  sevseg_array[1] = data;


  number = number / 10;
  num = number % 10;
  data = (unsigned char) num;
  data = NUMBERS[data];
  data &= 0xFE;  // insert decimal point - 2 decimal
  sevseg_array[2] = data;


 // number = number / 10;
 // num = number % 10;
 // data = (unsigned char) num;
 // data = NUMBERS[data];
  if(sign == 0) data = NUMBERS[10];   // minus sign
  else data = NUMBERS[11];            // blank
  sevseg_array[3] = data;
  
}




void ShiftOut_array(unsigned char sevseg_array[], unsigned char length)
{
  digitalWrite(LOAD_PIN,LOW);
  for (int i=0; i< length; i++){
    shiftOut(SDI_PIN, SCLK_PIN, LSBFIRST , sevseg_array[i]); 
  }
  digitalWrite(LOAD_PIN,HIGH);
}



/* ------------------------ */
/*  Set Change Up Down      */
/* ------------------------ */

void init_updwn( void)
{
  DDRC  &= ~( 1 << PC3 );    // PC3 '0' is input, Up 
  PORTC |=  ( 1 << PC3 );    // activate internal pullup

  DDRC  &= ~( 1 << PC2 );    // PC2 '0' is input, Dwn
  PORTC |=  ( 1 << PC2 );    // activate internal pullup

  
}


/* ------------------------ */
/*  PWM output              */
/* ------------------------ */

// Setup timer for 16 bit PWM
void init_PWM( void ) {

  TCCR1A = 1 << WGM11 | 1 << COM1A1;               // set on top, clear OC on compare match
 // TCCR1B = 1 << CS10  | 1 << WGM12 | 1 << WGM13;   // clk/1, mode 14 fast PWM
  TCCR1B = 1 << CS11  | 1 << WGM12 | 1 << WGM13;   // clk/8, mode 14 fast PWM
  ICR1 = MAX_PWM_VALUE;

  DDRB  |=  ( 1 << PB1 );      // "1" PWM-pin direction is output
}





/* *********************************** */
/*            HARDWARE                 */
/* *********************************** */

/*                     Chip ATMega328                          Arduino Uno R3 stackable header
                                                                              _______
                                                              Digital:  _____/       \__  Analog:
               ______________  ______________                   txd ->-|D00 >RXD      A5|-
              |              \/              |                  rxd -<-|D01 <TXD      A4|-
        Res---|01 PC6/RES' ATM328  SCL/PC5 28|-(A5)-      SEG7_Load -<-|D02           A3|-<- UP
 txd ->-(D00)-|02 PD0/RXD          SDA/PC4 27|-(A4)-      SEG7_SCLK -<-|D03~          A2|-<- DWN
 rxd -<-(D01)-|03 PD1/TXD              PC3 26|-(A3)- UP    SEG7_SDI -<-|D04           A1|-<-NTC_RET_OUT
   Load-(D02)-|04 PD2/INT0             PC2 25|-(A2)- DWN              -|D05~          A0|-<-NTC_FWD_OUT
   SCLK-(D03)-|05 PD3/INT1/PWM         PC1 24|-(A1)-<-NTC_REW_OUT     -|D06~            | Power:      
    SDI-(D04)-|06 PD4                  PC0 23|-(A0)-<-NTC_FWD_OUT     -|D07          Vin|-
       +5V ---|07 VCC                  GND 22|--- Gnd                  |             GND|--- GND
       Gnd ---|08 GND                 AREF 21|--- Vin                 -|D08          GND|- 
    Xtal |X|--|09 PB6/OSC1            AVCC 20|--- +5V                 -|D09~         +5V|--- +5V
   16MHz |X|--|10 PB7/OSC2         SCK/PB5 19|-(D13)-                 -|D10~       +3.3V|-
       -(D05)-|11 PD5/PWM         MISO/PB4 18|-(D12)-                 -|D11~         Res|-
       -(D06)-|12 PD6/PWM     PWM/MOSI/PB3 17|-(D11)-                 -|D12        IOREF|-
       -(D07)-|13 PD7          PWM/SS'/PB2 16|-(D10)-                 -|D13 LED     --- |
       -(D08)-|14 PB0              PWM/PB1 15|-                       -|GND             | 
              |______________________________|                        -|AREF            |
                                                                      -|SCL             |
                                                                      -|SDA             |
                                                                       |________________|
*/


/*
  74HC595 Shiftregister for 3 digit 7-segment display       
         ______________________________________
        |  SEG7  Active low '0' LED on         |
 +5V ---|Vcc      /-a-\                     Vcc|---
 GND ---|Gnd      f   b                     Gnd|---
 D04 ->-|SDI      |-g-|   a.b.c.d.e.f.g.dp  SDO|---
 D03 ->-|SCLK     e   c   lsb first        SCLK|---
 D02 ->-|Load     \-d-/ dp                 Load|---
        |______________________________________|
*/

/*
            ________________
           | NTC Thermistor |
  NTC_OUT -| NTC 10k        |
      VCC -| R 10k          |
      GND -|                |
           |________________|

*/

74HC595
74HC595
74HC595
74HC595
74HC595
74HC595
74HC595