/** \file maintask.c ******************************************************
 *
 *             Project: MAXREFDES82
 *             Filename: maintask.c
 *         Description: This module contains the major functions for the
 *                      implementation of the example program for the MAXREFDES82.
 *
 *    Revision History:
 *\n                    03-02-2016    Rev 03.50    MG    Initial release.
 *
 *
*******************************************************************************
* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated 
* Products, Inc. shall not be used except as stated in the Maxim Integrated 
* Products, Inc. Branding Policy.

* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all 
* ownership rights.
********************************************************************************/

#include "main.h"
#include "GUI.h"
#include "string.h"
#include "stm32f429i_discovery_lcd.h"
#include "stm32f4xx_hal.h"
#include "stm32f429i_discovery.h"
#include "math.h"

#define POWERUP_CAL_NUM 200
#define FACOTRY_CAL_NUM 200

#define MAJORVERSION 3
#define MINORVERSION 5
uint8_t usbTxBuf[32]={0};

/*Variable used for Erase procedure*/
static FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t SectorError = 0;
static void ErrorHandler(void); 

extern USBD_HandleTypeDef  USBD_Device;
uint8_t request = 0; 

GUI_RECT Rect = {0, 0, 320, 240}; 

uint8_t spiWritePacket[4] = {0};

// data registers from MAX11254. 
uint8_t data0[4], data1[4], data2[4], data3[4];									 

// data in binary offset format. 
uint32_t data0BO, data1BO, data2BO, data3BO;	
 
// load cell result in decimal format.  	
int cell0Load, cell1Load, cell2Load, cell3Load;	

// zero gram load reading
double cell0Load0=80606.899, cell1Load0=2316.475, cell2Load0=-4303.219, cell3Load0=48106.286;	
uint32_t cell0Load0Int, cell1Load0Int, cell2Load0Int, cell3Load0Int;	
uint32_t cell0Load0Sign, cell1Load0Sign, cell2Load0Sign, cell3Load0Sign;

// 700 gram load reading
double cell0Load700=1386219.167, cell1Load700=1306319.674, cell2Load700=1238527.327, cell3Load700=1278776.285;	
uint32_t cell0Load700Int, cell1Load700Int, cell2Load700Int, cell3Load700Int;	
uint32_t cell0Load700Sign, cell1Load700Sign, cell2Load700Sign, cell3Load700Sign;

// power up calibration results in decimal format. 
double cell0Powerup, cell1Powerup, cell2Powerup, cell3Powerup; 

// load in grams.
double cell0Grams, cell1Grams, cell2Grams, cell3Grams;

void ConfigureSPIandGPIO(void); 
void ConfigureMAX11254(void); 
void ReadMAX11254Results(void);
void Calibration(int8_t type, int32_t conversions);
	
double x=0, y=0, r=0;

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/
/*********************************************************************
*
*       MainTask
*/
void MainTask(void)
{
  //GUI_MEMDEV_Handle hMem = GUI_MEMDEV_Create(0,0,100,100);
	//GUI_MEMDEV_Select(hMem);	
  //GUI_MEMDEV_CopyToLCD(hMem);
	GUI_Clear();
  //GUI_SetFont(&GUI_Font16B_1);
	GUI_SetFont(&GUI_Font8x16); 
  
	ConfigureSPIandGPIO(); 
	HAL_Delay(5);
	
	ConfigureMAX11254(); 
	HAL_Delay(5);
  
  cell0Load0Sign = *(__IO uint32_t*)0x08100000;
  cell1Load0Sign = *(__IO uint32_t*)0x08100008;
  cell2Load0Sign = *(__IO uint32_t*)0x08100010;
  cell3Load0Sign = *(__IO uint32_t*)0x08100018;
  cell0Load700Sign = *(__IO uint32_t*)0x08100020;
  cell1Load700Sign = *(__IO uint32_t*)0x08100028;
  cell2Load700Sign = *(__IO uint32_t*)0x08100030;
  cell3Load700Sign = *(__IO uint32_t*)0x08100038;
  cell0Load0Int = *(__IO uint32_t*)0x08100004;
  cell1Load0Int = *(__IO uint32_t*)0x0810000C;
  cell2Load0Int = *(__IO uint32_t*)0x08100014;
  cell3Load0Int = *(__IO uint32_t*)0x0810001C;
  cell0Load700Int = *(__IO uint32_t*)0x08100024;
  cell1Load700Int = *(__IO uint32_t*)0x0810002C;
  cell2Load700Int = *(__IO uint32_t*)0x08100034;
  cell3Load700Int = *(__IO uint32_t*)0x0810003C;
  cell0Load0Sign==1? (cell0Load0 = 0.0-(double)cell0Load0Int):(cell0Load0 = cell0Load0Int);
  cell1Load0Sign==1? (cell1Load0 = 0.0-(double)cell1Load0Int):(cell1Load0 = cell1Load0Int);
  cell2Load0Sign==1? (cell2Load0 = 0.0-(double)cell2Load0Int):(cell2Load0 = cell2Load0Int);
  cell3Load0Sign==1? (cell3Load0 = 0.0-(double)cell3Load0Int):(cell3Load0 = cell3Load0Int); 
  cell0Load700Sign==1? (cell0Load700 = 0.0-(double)cell0Load700Int):(cell0Load700 = cell0Load700Int);
  cell1Load700Sign==1? (cell1Load700 = 0.0-(double)cell1Load700Int):(cell1Load700 = cell1Load700Int);
  cell2Load700Sign==1? (cell2Load700 = 0.0-(double)cell2Load700Int):(cell2Load700 = cell2Load700Int);
  cell3Load700Sign==1? (cell3Load700 = 0.0-(double)cell3Load700Int):(cell3Load700 = cell3Load700Int); 
  
  Calibration(0, POWERUP_CAL_NUM);	
	
	// loop forever.
	while(1)
	{			
		// start one conversion.
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
		spiWritePacket[0] = 0xB4; // 200 SPS 
		SPIx_Write_2(spiWritePacket, 1);		
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
		
		// wait for the conversion to complete. 		
		while(1)
		{		
			if(HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_13) == GPIO_PIN_RESET)
				break; 
		}		
		BSP_LED_Toggle(LED3);
		
		ReadMAX11254Results();
		
		// calculate results. 
    cell0Grams = (cell0Load - cell0Powerup) * 700.0 / (cell0Load700-cell0Load0);
		cell1Grams = (cell1Load - cell1Powerup) * 700.0 / (cell1Load700-cell1Load0);
		cell2Grams = (cell2Load - cell2Powerup) * 700.0 / (cell2Load700-cell2Load0);
		cell3Grams = (cell3Load - cell3Powerup) * 700.0 / (cell3Load700-cell3Load0);
 				
		x = 240-(cell1Grams+cell3Grams)/(cell0Grams+cell1Grams+cell2Grams+cell3Grams) * 240;
		y = 240-(cell0Grams+cell1Grams)/(cell0Grams+cell1Grams+cell2Grams+cell3Grams) * 240;
		r = (cell0Grams+cell1Grams+cell2Grams+cell3Grams)/500.0 * 120.0;
    
		GUI_ClearRect(0, 0, 240, 240);  
		GUI_FillCircle(x,y,r);	
    if (((cell0Grams+cell1Grams+cell2Grams+cell3Grams)<1) && ((cell0Grams+cell1Grams+cell2Grams+cell3Grams)>-1))
      GUI_ClearRect(0, 0, 240, 240);

		char string5[200];

		sprintf(string5, "Smart Force Sensor\nLoad1=%6.1f g Load4=%6.1f g\nLoad2=%6.1f g Load3=%6.1f g\nTotal Load=%6.1f g",
		cell0Grams, cell2Grams, cell1Grams, cell3Grams, cell0Grams+cell1Grams+cell2Grams+cell3Grams);
		//GUI_RECT Rect = {241, 0, 320, 240};
	  Rect.x0 = 241;
    Rect.y0 = 0;
    Rect.x1 = 320;
    Rect.y1 = 240; 
    //char acText[] = &string1[0];
	  GUI_SetTextMode(GUI_TM_XOR);
	  GUI_FillRectEx(&Rect);
	  //GUI_DispStringInRectEx(acText, &Rect, GUI_TA_HCENTER | GUI_TA_VCENTER, strlen(acText), GUI_ROTATE_CW);
		GUI_DispStringInRectEx(string5, &Rect, GUI_TA_HCENTER | GUI_TA_VCENTER, strlen(string5), GUI_ROTATE_CW);
    
    
    // send data to PC    
    if(request == 0xFF)   // host request handshake
    {
      
      request = 0;   // clear
      usbTxBuf[0] = 0xFE;    
      usbTxBuf[1] = MAJORVERSION; 
      usbTxBuf[2] = MINORVERSION;
      
      USBD_CDC_SetTxBuffer(&USBD_Device, &usbTxBuf[0], 32);
      if(USBD_Device.dev_state == USBD_STATE_CONFIGURED)
        USBD_CDC_TransmitPacket(&USBD_Device);
      
    }
    else if (request == 0xFD) // host request data
    {      
      usbTxBuf[0] = 0xFC; 
      
      usbTxBuf[1] = (cell0Grams > 0)? 1:0; 
      usbTxBuf[2] = abs(cell0Grams)/100; 
      usbTxBuf[3] = abs(cell0Grams)%100;
      usbTxBuf[4] = abs(cell0Grams*10.0)%10;
      
      usbTxBuf[5] = (cell1Grams > 0)? 1:0; 
      usbTxBuf[6] = abs(cell1Grams)/100; 
      usbTxBuf[7] = abs(cell1Grams)%100;
      usbTxBuf[8] = abs(cell1Grams*10.0)%10;
      
      usbTxBuf[9]  = (cell3Grams > 0)? 1:0; 
      usbTxBuf[10] = abs(cell3Grams)/100; 
      usbTxBuf[11] = abs(cell3Grams)%100;
      usbTxBuf[12] = abs(cell3Grams*10.0)%10;
      
      usbTxBuf[13]  = (cell2Grams > 0)? 1:0; 
      usbTxBuf[14] = abs(cell2Grams)/100; 
      usbTxBuf[15] = abs(cell2Grams)%100;
      usbTxBuf[16] = abs(cell2Grams*10.0)%10; 
      
      usbTxBuf[17]  = (x > 0)? 1:0; 
      usbTxBuf[18] = abs(x)/100; 
      usbTxBuf[19] = abs(x)%100;
      
      usbTxBuf[20]  = (y > 0)? 1:0;
      usbTxBuf[21] = abs(y)/100; 
      usbTxBuf[22] = abs(y)%100;
      
      usbTxBuf[23]  = (r > 0)? 1:0;
      usbTxBuf[24] = abs(r)/100; 
      usbTxBuf[25] = abs(r)%100;
      
      USBD_CDC_SetTxBuffer(&USBD_Device, &usbTxBuf[0], 32);
      
      if(USBD_Device.dev_state == USBD_STATE_CONFIGURED)
        USBD_CDC_TransmitPacket(&USBD_Device);
    
    }
    else if (request == 0xFB)  // host request stop streaming 
      request = 0;
  
    // check if SW2 is pressed. 
		if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) == GPIO_PIN_RESET)	
		// factory calibration.
		{   
      char string[] = "Factory Calibration!\n\n\
If You Are Not\n\n\
Factory Calibrator\n\n\
Release\n\n\
***SW2***\n\n\
Immediately!\n\n\n\
Otherwise, Hold On\n\n\
For 5 Seconds\n\n\
Then Release SW2";
      GUI_Clear();
      Rect.x0 = 0;
      Rect.y0 = 0;
      Rect.x1 = 320;
      Rect.y1 = 240;
      GUI_SetTextMode(GUI_TM_XOR);
      GUI_FillRectEx(&Rect);
      GUI_DispStringInRectEx(string, &Rect, GUI_TA_HCENTER | GUI_TA_VCENTER, strlen(string), GUI_ROTATE_CW);
      HAL_Delay(5000);      

      if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) != GPIO_PIN_SET)
      {        
        // start after SW2 is released, otherwise, type 1 "PRESS SW2 WHEN READY" SCREEN will be missed. 
        while(1)
        {
          if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) == GPIO_PIN_SET)
            break;        
        }
        
        Calibration(1, FACOTRY_CAL_NUM);
        Calibration(2, FACOTRY_CAL_NUM);
        Calibration(3, FACOTRY_CAL_NUM);
        Calibration(4, FACOTRY_CAL_NUM);
        Calibration(5, FACOTRY_CAL_NUM);
        
        cell0Load0<0? (cell0Load0Sign=1):(cell0Load0Sign=0);
        cell0Load0Int = abs(cell0Load0); 
        cell1Load0<0? (cell1Load0Sign=1):(cell1Load0Sign=0);
        cell1Load0Int = abs(cell1Load0);
        cell2Load0<0? (cell2Load0Sign=1):(cell2Load0Sign=0);
        cell2Load0Int = abs(cell2Load0);
        cell3Load0<0? (cell3Load0Sign=1):(cell3Load0Sign=0);
        cell3Load0Int = abs(cell3Load0);
        
        cell0Load700<0? (cell0Load700Sign=1):(cell0Load700Sign=0);
        cell0Load700Int = abs(cell0Load700); 
        cell1Load700<0? (cell1Load700Sign=1):(cell1Load700Sign=0);
        cell1Load700Int = abs(cell1Load700);
        cell2Load700<0? (cell2Load700Sign=1):(cell2Load700Sign=0);
        cell2Load700Int = abs(cell2Load700);
        cell3Load700<0? (cell3Load700Sign=1):(cell3Load700Sign=0);
        cell3Load700Int = abs(cell3Load700);
        
        /* Unlock the Flash to enable the flash control register access *************/ 
        HAL_FLASH_Unlock();
        /* Fill EraseInit structure*/
        EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
        EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
        EraseInitStruct.Sector = FLASH_SECTOR_12;
        EraseInitStruct.NbSectors = 1;
        if(HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK)
          ErrorHandler(); 
        
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08100000, cell0Load0Sign) != HAL_OK)
          ErrorHandler();
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08100008, cell1Load0Sign) != HAL_OK)
          ErrorHandler();
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08100010, cell2Load0Sign) != HAL_OK)
          ErrorHandler();
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08100018, cell3Load0Sign) != HAL_OK)
          ErrorHandler();
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08100020, cell0Load700Sign) != HAL_OK)
          ErrorHandler();
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08100028, cell1Load700Sign) != HAL_OK)
          ErrorHandler();
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08100030, cell2Load700Sign) != HAL_OK)
          ErrorHandler();
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08100038, cell3Load700Sign) != HAL_OK)
          ErrorHandler(); 
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08100004, cell0Load0Int) != HAL_OK)
          ErrorHandler();
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x0810000C, cell1Load0Int) != HAL_OK)
          ErrorHandler();         
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08100014, cell2Load0Int) != HAL_OK)
          ErrorHandler();
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x0810001C, cell3Load0Int) != HAL_OK)
          ErrorHandler();
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08100024, cell0Load700Int) != HAL_OK)
          ErrorHandler();
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x0810002C, cell1Load700Int) != HAL_OK)
          ErrorHandler();         
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08100034, cell2Load700Int) != HAL_OK)
          ErrorHandler();
        if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x0810003C, cell3Load700Int) != HAL_OK)
          ErrorHandler();
        
        HAL_FLASH_Lock(); 
        
      } // factory calibartion
    } // factory calibration
	} // while(1) 
} // MainTask()


void ConfigureSPIandGPIO(void)
{
	// Configure U1_RSTB pin: PG14
	GPIO_InitTypeDef   GPIO_InitStructure;
  GPIO_InitStructure.Pin     = GPIO_PIN_14;
  GPIO_InitStructure.Mode    = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStructure.Pull    = GPIO_NOPULL;
  GPIO_InitStructure.Speed   = GPIO_SPEED_FAST;
  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); 
	
	HAL_GPIO_WritePin(GPIOG, GPIO_PIN_14, GPIO_PIN_RESET);
	HAL_Delay(1); 
	HAL_GPIO_WritePin(GPIOG, GPIO_PIN_14, GPIO_PIN_SET);

	// Configure U1_RDYB pin: PG13
	GPIO_InitStructure.Pin     = GPIO_PIN_13;
  GPIO_InitStructure.Mode    = GPIO_MODE_INPUT;
  GPIO_InitStructure.Pull    = GPIO_PULLUP;
  GPIO_InitStructure.Speed   = GPIO_SPEED_FAST;
  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
		
	// Configure U1_CSB pin: PA15
	GPIO_InitStructure.Pin     = GPIO_PIN_15;
  GPIO_InitStructure.Mode    = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStructure.Pull    = GPIO_NOPULL;
  GPIO_InitStructure.Speed   = GPIO_SPEED_FAST;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// Configure SW2, PA8
	GPIO_InitStructure.Pin     = GPIO_PIN_8;
  GPIO_InitStructure.Mode    = GPIO_MODE_INPUT;
  GPIO_InitStructure.Pull    = GPIO_PULLUP;
  GPIO_InitStructure.Speed   = GPIO_SPEED_FAST;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
		
	SPIx_Init();		
}

void ConfigureMAX11254(void) 
{
	//SEQ
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
	spiWritePacket[0] = 0xD0; 
	spiWritePacket[1] = 0x0B;	 
	SPIx_Write_2(spiWritePacket, 2);		
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
	
	//DELAY
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
	spiWritePacket[0] = 0xCA; 
	spiWritePacket[1] = 0xFF;
	spiWritePacket[2] = 0x00;		
	SPIx_Write_2(spiWritePacket, 3);		
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
	
	//CTRL3
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
	spiWritePacket[0] = 0xC6; 
	spiWritePacket[1] = 0x1C; 
	SPIx_Write_2(spiWritePacket, 2);		
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);

	//CHMAP0
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
	spiWritePacket[0] = 0xCE; 
	spiWritePacket[1] = 0x0B;					
	spiWritePacket[2] = 0x27;					
	spiWritePacket[3] = 0x4F;						
	SPIx_Write_2(spiWritePacket, 4);		
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);

	//CHMAP1
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
	spiWritePacket[0] = 0xCC; 
	spiWritePacket[1] = 0x00;
	spiWritePacket[2] = 0x00;
	spiWritePacket[3] = 0x73;	
	SPIx_Write_2(spiWritePacket, 4);		
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
	
	//CTRL2
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
	spiWritePacket[0] = 0xC4; 
	// gain = 128 or 0?
	//spiWritePacket[1] = 0x20;	
  spiWritePacket[1] = 0x2F;				
	SPIx_Write_2(spiWritePacket, 2);		
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
	
	
	//CTRL1
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
	spiWritePacket[0] = 0xC2; 
	// input=bipolar, fromat=offset binary, SCYCLE=1, CONTSC=0. 
	spiWritePacket[1] = 0x06; 			
	SPIx_Write_2(spiWritePacket, 2);		
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);	
}

void ReadMAX11254Results(void)
{
	// ch0
	spiWritePacket[0]= 0xDD;
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
	SPIx_WriteRead_2(spiWritePacket, data0, 4);						//ch0 
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
		
	data0BO = ((data0[1] << 16) + (data0[2] << 8) + data0[3]);
	cell0Load = data0BO - 0x800000; 
	
	// ch1
	spiWritePacket[0]= 0xDF;
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
	SPIx_WriteRead_2(spiWritePacket, data1, 4);	
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);

	data1BO = ((data1[1] << 16) + (data1[2] << 8) + data1[3]);
	cell1Load = data1BO - 0x800000;

	// ch2
	spiWritePacket[0]= 0xE1;
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
	SPIx_WriteRead_2(spiWritePacket, data2, 4);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
	
	data2BO = ((data2[1] << 16) + (data2[2] << 8) + data2[3]);
	cell2Load = data2BO - 0x800000; 
  
	// ch3
	spiWritePacket[0]= 0xE3;
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
	SPIx_WriteRead_2(spiWritePacket, data3, 4);	
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
	
	data3BO = ((data3[1] << 16) + (data3[2] << 8) + data3[3]);
	cell3Load = data3BO - 0x800000;
}

// type: 0-powerup, 1-factory 0 load, 2-cell0 700 g, 
// 3-cell1 700g, 4-cell2 700g, 5-cell3 700g.  
void Calibration(int8_t type, int32_t conversions)
{
	
  char string00[] = "Powerup Calibration:\n\n\n\n\n\
Remove Everything\n\n\
On The Top\n\n\n\
Place The Board\n\n\
On A Flat Surface\n\n\n\
Press SW2 When Ready";
  
  char string01[] = "Powerup Calibration:\n\n\n\n\n\
Remove Everything\n\n\
On The Top\n\n\n\
Place The Board\n\n\
On A Flat Surface\n\n\n\
Do Not Touch The Board";
  
  char string10[] = "Factory 0 Load Calibration:\n\n\n\n\n\
Remove Everything\n\n\
On The Sensors\n\n\n\
Place The Board\n\n\
On A Flat Surface\n\n\n\
Press SW2 When Ready";

  char string11[] = "Factory 0 Load Calibration:\n\n\n\n\n\
Remove Everything\n\n\
On The Sensors\n\n\n\
Place The Board\n\n\
On A Flat Surface\n\n\n\
Do Not Touch The Board";
 
  char string20[] = "Factory 700g Load Calibration:\n\n\n\n\n\
Place 700 gram Weight\n\n\
On The Load Cell --1--\n\n\n\
Place The Board\n\n\
On A Flat Surface\n\n\n\
Press SW2 When Ready";

  char string21[] = "Factory 700g Load Calibration:\n\n\n\n\n\
Place 700 gram Weight\n\n\
On The Load Cell --1--\n\n\n\
Place The Board\n\n\
On A Flat Surface\n\n\n\
Do Not Touch The Board";

  char string30[] = "Factory 700g Load Calibration:\n\n\n\n\n\
Place 700 gram Weight\n\n\
On The Load Cell --2--\n\n\n\
Place The Board\n\n\
On A Flat Surface\n\n\n\
Press SW2 When Ready";

  char string31[] = "Factory 700g Load Calibration:\n\n\n\n\n\
Place 700 gram Weight\n\n\
On The Load Cell --2--\n\n\n\
Place The Board\n\n\
On A Flat Surface\n\n\n\
Do Not Touch The Board"; 

  char string40[] = "Factory 700g Load Calibration:\n\n\n\n\n\
Place 700 gram Weight\n\n\
On The Load Cell --3--\n\n\n\
Place The Board\n\n\
On A Flat Surface\n\n\n\
Press SW2 When Ready";

  char string41[] = "Factory 700g Load Calibration:\n\n\n\n\n\
Place 700 gram Weight\n\n\
On The Load Cell --3--\n\n\n\
Place The Board\n\n\
On A Flat Surface\n\n\n\
Do Not Touch The Board";

  char string50[] = "Factory 700g Load Calibration:\n\n\n\n\n\
Place 700 gram Weight\n\n\
On The Load Cell --4--\n\n\n\
Place The Board\n\n\
On A Flat Surface\n\n\n\
Press SW2 When Ready";

  char string51[] = "Factory 700g Load Calibration:\n\n\n\n\n\
Place 700 gram Weight\n\n\
On The Load Cell --4--\n\n\n\
Place The Board\n\n\
On A Flat Surface\n\n\n\
Do Not Touch The Board";

  char *string0, *string1;
  Rect.x0 = 0;
  Rect.y0 = 0;
  Rect.x1 = 320;
  Rect.y1 = 240; 
    
  switch (type)
  {
    case 0:
      string0 = string00;
      string1 = string01;
    break;    
    case 1:
      string0 = string10;
      string1 = string11;
    break;
    case 2:
      string0 = string20;
      string1 = string21;
    break;
    case 3:
      string0 = string30;
      string1 = string31;
    break;
    case 4:
      string0 = string40;
      string1 = string41;
    break;
    case 5:
      string0 = string50;
      string1 = string51;
    break;
    default:
      ;
  }
  GUI_Clear();
  GUI_SetTextMode(GUI_TM_XOR);
  GUI_FillRectEx(&Rect);
  GUI_DispStringInRectEx(string0, &Rect, GUI_TA_HCENTER | GUI_TA_VCENTER, strlen(string0), GUI_ROTATE_CW);
  
  // wait for SW2 being pressed  
  while(1)
  {
    if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) == GPIO_PIN_RESET)
      break;           
  }
  GUI_Clear();
  GUI_SetTextMode(GUI_TM_XOR);
  GUI_FillRectEx(&Rect);
  GUI_DispStringInRectEx(string1, &Rect, GUI_TA_HCENTER | GUI_TA_VCENTER, strlen(string1), GUI_ROTATE_CW);

	GUI_Delay(5000);  // wait for the board to be stable.  
	
	int32_t loop = 0; 
  double cell0Total = 0, cell1Total = 0, cell2Total = 0, cell3Total = 0; 
	for(loop = 0; loop < conversions; loop++)
	{
		// start one conversion.
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
		spiWritePacket[0] = 0xB4;			// 200 SPS
		SPIx_Write_2(spiWritePacket, 1);		
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
		
		// wait for conversion to complete.
		while(1)
		{		
			if(HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_13) == GPIO_PIN_RESET)
				break; 
		}			
		BSP_LED_Toggle(LED3);
		
		ReadMAX11254Results();
		
		cell0Total += cell0Load; 
		cell1Total += cell1Load; 
		cell2Total += cell2Load; 
		cell3Total += cell3Load;		
	}
  
  switch (type)
  {
    case 0:
      cell0Powerup = cell0Total/conversions; 
      cell1Powerup = cell1Total/conversions; 
      cell2Powerup = cell2Total/conversions; 
      cell3Powerup = cell3Total/conversions;
    break;
    case 1:
      cell0Load0 = cell0Total/conversions; 
      cell1Load0 = cell1Total/conversions; 
      cell2Load0 = cell2Total/conversions; 
      cell3Load0 = cell3Total/conversions;
    break;
    case 2:
      cell0Load700 = cell0Total/conversions;  // LOADCELL1=cell0 
    break;
    case 3:
      cell1Load700 = cell1Total/conversions;  // LOADCELL2=cell1
    break;    
    case 4:
      cell3Load700 = cell3Total/conversions;  // LOADCELL3=cell3 
    break;
    case 5:
      cell2Load700 = cell2Total/conversions;  // LOADCELL4=cell2 
    break;
    default:
      ;
  }
}	

static void ErrorHandler(void)
{
  while(1)
  {
    HAL_Delay(200); 
    BSP_LED_Toggle(LED2);
  }  
}
/*************************** End of file ****************************/
