/* --COPYRIGHT--,BSD_EX
 * Copyright (c) 2013, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *******************************************************************************
 * 
 *                       MSP430 CODE EXAMPLE DISCLAIMER
 *
 * MSP430 code examples are self-contained low-level programs that typically
 * demonstrate a single peripheral function or device feature in a highly
 * concise manner. For this the code may rely on the device's power-on default
 * register values and settings such as the clock configuration and care must
 * be taken when combining code from several examples to avoid potential side
 * effects. Also see www.ti.com/grace for a GUI- and www.ti.com/msp430ware
 * for an API functional library-approach to peripheral configuration.
 *
 * --/COPYRIGHT--*/
//******************************************************************************
//  MSP430i20xx IR Thermometer demo, loading calibration data to INFO memory and preserving TLV data.
//
//
//
//  ACLK = 32kHz, MCLK = SMCLK = Calibrated DCO = 16.384MHz
//  * Ensure low_level_init.c is included when building/running this example *
//
//               MSP430i20xx
//             -----------------
//         /|\|                |
//          | |                |
//          --|RST             |
//            |                |
//
//  JD Crutchfield
//  Texas Instruments, Inc
//  July 2020
//  Built with Code Composer Studio v9.3
//******************************************************************************
#include "msp430.h"




/*
 * ************** Calibration Data **********************
 */
//These constants are not currently used in the latest demo.
const long CalibrationThermopileOffset = 1;
const long CalibrationThermopileScalingFactor = 1;
const long CalibrationThermistorOffset = 1;

// Scaling factor in %. 100 = 1   94 = .94, ect
const long S_CONV_x100 = 100;

//Thermopile Lookup Table
#define LUT_LENGTH      51
const long ThermopileLUT[LUT_LENGTH] = // Gain 200
{   -1811012    ,
    -1753060    ,
    -1695107    ,
    -1622667    ,
    -1564714    ,
    -1506762    ,
    -1434321    ,
    -1361881    ,
    -1303929    ,
    -1231488    ,
    -1159048    ,
    -1086607    ,
    -1014167    ,
    -941726 ,
    -869286 ,
    -796845 ,
    -724405 ,
    -651964 ,
    -565036 ,
    -492595 ,
    -405667 ,
    -333226 ,
    -246298 ,
    -173857 ,
    -86929  ,
    0   ,
    86929   ,
    173857  ,
    260786  ,
    347714  ,
    434643  ,
    521571  ,
    622988  ,
    709917  ,
    811333  ,
    898262  ,
    999679  ,
    1086607 ,
    1188024 ,
    1289441 ,
    1390857 ,
    1492274 ,
    1593691 ,
    1695107 ,
    1796524 ,
    1897941 ,
    1999357 ,
    2115262 ,
    2216679 ,
    2332583 ,
    2434000
};

//Thermistor Lookup Table
static const long ThermistorLUT[LUT_LENGTH] =
{     8164168   ,
      8029826 ,
      7893910 ,
      7756577 ,
      7617980 ,
      7478284 ,
      7337653 ,
      7196254 ,
      7054262 ,
      6911841 ,
      6769165 ,
      6626404 ,
      6483727 ,
      6341298 ,
      6199284 ,
      6057834 ,
      5917101 ,
      5777242 ,
      5638403 ,
      5500739 ,
      5364329 ,
      5229352 ,
      5095887 ,
      4964082 ,
      4833779 ,
      4705779 ,
      4579477 ,
      4455174 ,
      4332921 ,
      4212837 ,
      4094949 ,
      3979290 ,
      3865936 ,
      3754902 ,
      3646177 ,
      3539877 ,
      3435948 ,
      3334385 ,
      3235244 ,
      3138525 ,
      3044166 ,
      2952212 ,
      2862606 ,
      2775363 ,
      2690487 ,
      2607869 ,
      2527531 ,
      2449431 ,
      2373517 ,
      2299824 ,
      2228226
};

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

void SaveMSP430TLVdata(void);
void EraseInfoMemory(void);
void WriteCalibrationDataToInfoMemory(void);

#define TLV_ADDRESS     0x13C0
unsigned int TLV_Data[(TLV_END - TLV_START)/2 + 1] = {0};
unsigned int TLVlength = (TLV_END - TLV_START)/2 + 1;



void main(void) {
    WDTCTL = WDTPW | WDTHOLD;     // Stop Watchdog Timer

    __delay_cycles(32000000);

    SaveMSP430TLVdata();

    EraseInfoMemory();

    WriteCalibrationDataToInfoMemory();

    while(1) {
        __no_operation();
        LPM0;
    }
}




void SaveMSP430TLVdata(void) {  //Read from Flash
    int *ptrRead;
    int x;

    ptrRead = (int *)TLV_ADDRESS; //Point to beginning of information memory

    for(x=0; x<TLVlength; x++){
        TLV_Data[x] = *ptrRead++;
    }
}


void EraseInfoMemory(void) { //Erase Information Memory Segment

    int *ptrErase;

    ptrErase =(int *) 0x1000; //pointer to beginning of InfoFlash Segment

    FCTL2 = FWKEY + FSSEL1 + 37;//Divide SMCLK(16.3MHz) by 38
    FCTL1 = FWKEY + ERASE; //Put into erase segment mode
    if(FCTL3 & LOCKSEG){  //Info mem is locked, need to unlock
        FCTL3 = FWKEY + LOCKSEG;  // Unlock info mem
    }
    else{
        FCTL3 = FWKEY; //unlock flash
    }

    *ptrErase = 0; //dummy value to erase Flash

    FCTL3 = FWKEY + LOCKSEG + LOCK; //lock flash
}



void WriteCalibrationDataToInfoMemory(void) {
    int x;
    int *ptrTLVFlash;
    long *calibrationFlash;

    ptrTLVFlash =(int *) TLV_ADDRESS;

    FCTL2 = FWKEY + FSSEL1 + 25; //Divide SMCLK
    if(FCTL3 & LOCKSEG){  //Info mem is locked, need to unlock
        FCTL3 = FWKEY + LOCKSEG;  // Unlock info mem
    }
    else{
        FCTL3 = FWKEY; //unlock flash
    }

    FCTL1 = FWKEY + WRT; //Set Write

    //Restore TLV after erase
    for(x=0; x<TLVlength; x++){  *ptrTLVFlash++ = TLV_Data[x]; }

    //Write Calibration data
    calibrationFlash =(long *) 0x1000;

    *calibrationFlash++ = CalibrationThermopileOffset;
    *calibrationFlash++ = CalibrationThermopileScalingFactor;
    *calibrationFlash++ = CalibrationThermistorOffset;
    *calibrationFlash++ = S_CONV_x100;
    for(x=0; x<LUT_LENGTH; x++){ *calibrationFlash++ = ThermopileLUT[x]; }
    for(x=0; x<LUT_LENGTH; x++){ *calibrationFlash++ = ThermistorLUT[x]; }



    FCTL1 = FWKEY; //Clear Write
    FCTL3 = FWKEY + LOCKSEG + LOCK; //Lock Flash
}







