/**
******************************************************************************
* @file           pch_sensors.c
* @brief          Работа с датчиками температуры DS18B20 в ПЧ
*****************************************************************************/


/* Includes ----------------------------------------------------------------*/

#include "PY32module_main.h"
#include "rs_message.h"

/* Declarations and definitions --------------------------------------------*/
PCHSens_TypeDef pchsens;
PCHSens_DallasBusHandle DallasBus;
static uint8_t scan_cnt;

/* Functions ---------------------------------------------------------------*/
void PYModule_FillResponse(PCHSens_SensorTypeDef* sensor, Sensor_ResponseStatusTypeDef status);
void PYModule_CheckModuleLosted(PCHSens_ModuleTypeDef *module, uint8_t *losted_flag);
void PYModule_StoreModuleToModbus(PCHSens_ModuleTypeDef *module);

void PYModule_main(void)
{
  
  if(MB_DATA.Coils.RunConvertions)
  {
    if(DS18B20_WaitForEndConvertion_NonBlocking(hdallas1.onewire) == HAL_OK)
    {
      PCHSens_StartCovert(&DallasBus);
      GPIOA->ODR ^= GPIO_LED_2; 
    }
  }
  
  if(MB_DATA.Coils.ReadSensor)
  {
    PYModule_ReadSensor(&hdallas1, &pchsens);
    MB_DATA.Coils.ReadSensor = 0;
  }
  
//  if(MB_DATA.Coils.ScanSensors)
//  {
//    PYModule_ScanSensor(&DallasBus);
//  }
//  else
//  {
//    scan_cnt = 0;
//  }
  
  if(MB_DATA.Coils.InitSensor)
  {
    PYModule_InitSensor(&pchsens);
    MB_DATA.Coils.InitSensor = 0;
  }
   
  if(MB_DATA.Coils.DeInitSensor != NULL)
  {
    PYModule_DeInitSensor(&pchsens);
    MB_DATA.Coils.DeInitSensor = 0;
  }
  
  PYModule_CheckLosted(&pchsens);
   
  if(MB_DATA.Coils.RunConvertions)
  {
    if(DS18B20_WaitForEndConvertion_NonBlocking(hdallas1.onewire) == HAL_OK)
    {
      PCHSens_ModuleReadTemperature(&pchsens.module1);
//      PCHSens_ModuleReadTemperature(&pchsens.module2);
//      PCHSens_ModuleReadTemperature(&pchsens.module3);
//      PCHSens_ModuleReadTemperature(&pchsens.module4);
//      PCHSens_ModuleReadTemperature(&pchsens.module5);
//      PCHSens_ModuleReadTemperature(&pchsens.module6);
      
      PYModule_StoreModbus(&pchsens);
    }
  }
  
}


void PYModule_FirstInit(void)
{  
  OW.DataPin = DS_Pin;
  OW.DataPort = DS_GPIO_Port;
  
  /* Инициализация onewire и поиск датчиков*/
  DS = (DS18B20_Drv_t *)&MB_DATA.InRegs.AllROMs;
	OneWire_Init(&OW);
  DS18B20_Search(DS, &OW);


  /* Инициализация modbus */
  MODBUS_FirstInit();
  RS_Receive_IT(&hmodbus1, &MODBUS_MSG);
  
  /* Инициализация структур датчиков ПЧ */
  DallasBus.hdallas = &hdallas1;
  DallasBus.hdallas->onewire = &OW;  
  DallasBus.hdallas->ds_devices = DS;
  PCHSens_InitModule(&hdallas1, &pchsens.module1, REG_PCH_NUMB_11|REG_PCH_DIODE_NUMB_1);
//  PCHSens_InitModule(&hdallas1, &pchsens.module2, REG_PCH_NUMB_12|REG_PCH_DIODE_NUMB_1);
//  PCHSens_InitModule(&hdallas1, &pchsens.module3, REG_PCH_NUMB_21|REG_PCH_DIODE_NUMB_1);
//  PCHSens_InitModule(&hdallas1, &pchsens.module4, REG_PCH_NUMB_22|REG_PCH_DIODE_NUMB_1);
//  PCHSens_InitModule(&hdallas1, &pchsens.module5, REG_PCH_NUMB_31|REG_PCH_DIODE_NUMB_1);
//  PCHSens_InitModule(&hdallas1, &pchsens.module6, REG_PCH_NUMB_32|REG_PCH_DIODE_NUMB_1);
  
  /* Поиск неизвестных сенсоров */
  PCHSens_FindUnknownSensors(&DallasBus);
  
  MB_DATA.Coils.RunConvertions = 1;
}


void PYModule_ScanSensor(PCHSens_DallasBusHandle *hbus)
{
  PCHSens_SensorTypeDef sensor;
  sensor.sens.hdallas = hbus->hdallas;
  sensor.sens.sensROM = *(uint64_t *)(hbus->hdallas->ds_devices->DevAddr[scan_cnt]);
  if (scan_cnt >= hbus->hdallas->onewire->RomCnt)
  {
    scan_cnt = hbus->hdallas->onewire->RomCnt;
    PYModule_FillResponse(&sensor, STATUS_SCAN_END);
    return;
  }
  if(Dallas_ReadScratchpad(&sensor.sens) == HAL_OK)
  {
    PYModule_FillResponse(&sensor, STATUS_OK);
  }
  else
  {
    PYModule_FillResponse(&sensor, STATUS_ERR_SCAN);
  }
}
void PYModule_IncrementScanSensor(void)
{
  if(MB_DATA.Coils.ScanSensors)
  {
    scan_cnt++;
  }
}
void PYModule_ReadSensor(DALLAS_HandleTypeDef *hdallas, PCHSens_TypeDef *pchsens)
{
  // чтение по локации
  if(MB_DATA.HoldRegs.InitStruct.Location != 0)  // если локация не равна нулю
  {
    PCHSens_SensorTypeDef *sensor;
    
    if(PCHSens_GetSensorByLocation(pchsens, (PCHSens_LocationTypeDef)MB_DATA.HoldRegs.InitStruct.Location, &sensor) != HAL_OK)
      return;
    
    if(Dallas_ReadScratchpad(&sensor->sens) == HAL_OK)
    {
      PYModule_FillResponse(sensor, STATUS_OK);
    }
    else
    {
      PYModule_FillResponse(sensor, STATUS_ERR_READ_LOCATION);
    }
  }
  // чтение по ROM
  else if(MB_DATA.HoldRegs.InitStruct.ROM[0] | MB_DATA.HoldRegs.InitStruct.ROM[1] | // если РОМ не равен нулю
      MB_DATA.HoldRegs.InitStruct.ROM[2] | MB_DATA.HoldRegs.InitStruct.ROM[3] != 0)
  {      
    PCHSens_SensorTypeDef sensor;
    sensor.sens.hdallas = hdallas;
    sensor.sens.sensROM = *(uint64_t *)MB_DATA.HoldRegs.InitStruct.ROM;
    
    if(Dallas_ReadScratchpad(&sensor.sens) == HAL_OK)
    {
      PYModule_FillResponse(&sensor, STATUS_OK);
    }
    else
    {
      PYModule_FillResponse(&sensor, STATUS_ERR_READ_ROM);
    }
  }
    
  
}

void PYModule_InitSensor(PCHSens_TypeDef *pchsens)
{
  if( (MB_DATA.HoldRegs.InitStruct.Location != 0) && // если локация не равна нулю
      (MB_DATA.HoldRegs.InitStruct.ROM[0] | MB_DATA.HoldRegs.InitStruct.ROM[1] | // И если РОМ не равен нулю
      MB_DATA.HoldRegs.InitStruct.ROM[2] | MB_DATA.HoldRegs.InitStruct.ROM[3] != 0) )
  {
    PCHSens_SensorTypeDef *sensor;
    
    if(PCHSens_GetSensorByLocation(pchsens, (PCHSens_LocationTypeDef)MB_DATA.HoldRegs.InitStruct.Location, &sensor) != HAL_OK)
      return;
    uint64_t connectROM = 0;
    connectROM =  ((uint64_t)(__REV16(MB_DATA.HoldRegs.InitStruct.ROM[0])))<<48;
    connectROM |= ((uint64_t)(__REV16(MB_DATA.HoldRegs.InitStruct.ROM[1])))<<32;
    connectROM |= ((uint64_t)(__REV16(MB_DATA.HoldRegs.InitStruct.ROM[2])))<<16;
    connectROM |= ((uint64_t)(__REV16(MB_DATA.HoldRegs.InitStruct.ROM[3])));
    
    if(PCHSens_InitNewSensor(&hdallas1, sensor, connectROM) == HAL_OK)
    {
      PYModule_FillResponse(sensor, STATUS_OK);
    }
    else
    {
      PYModule_FillResponse(sensor, STATUS_ERR_INIT);
    }
  }  
}

void PYModule_DeInitSensor(PCHSens_TypeDef *pchsens)
{
  if(MB_DATA.HoldRegs.InitStruct.Location != 0) // если локация не равна нулю
  {
    PCHSens_SensorTypeDef *sensor;
    
    if(PCHSens_GetSensorByLocation(pchsens, (PCHSens_LocationTypeDef)MB_DATA.HoldRegs.InitStruct.Location, &sensor) != HAL_OK)
      return;
    
    if(PCHSens_UndefineSensor(sensor) == HAL_OK)
    {
      PYModule_FillResponse(sensor, STATUS_OK);
    }
    else
    {
      PYModule_FillResponse(sensor, STATUS_ERR_DEINIT);
    }
  }  
}

void PYModule_CheckLosted(PCHSens_TypeDef *pchsens)
{
  uint8_t losted = 0;
  
  // module1
  PYModule_CheckModuleLosted(&pchsens->module1, &losted);
  PYModule_CheckModuleLosted(&pchsens->module2, &losted);
  PYModule_CheckModuleLosted(&pchsens->module3, &losted);
  PYModule_CheckModuleLosted(&pchsens->module4, &losted);
  PYModule_CheckModuleLosted(&pchsens->module5, &losted);
  PYModule_CheckModuleLosted(&pchsens->module6, &losted);
  
  if(losted)
    MB_DATA.Coils.LostedSensors = 1;
  else
    MB_DATA.Coils.LostedSensors = 0;
}

void PYModule_StoreModbus(PCHSens_TypeDef *pchsens)
{
  uint8_t losted = 0;
  
  // module1
  PYModule_StoreModuleToModbus(&pchsens->module1);
  PYModule_StoreModuleToModbus(&pchsens->module2);
  PYModule_StoreModuleToModbus(&pchsens->module3);
  PYModule_StoreModuleToModbus(&pchsens->module4);
  PYModule_StoreModuleToModbus(&pchsens->module5);
  PYModule_StoreModuleToModbus(&pchsens->module6);
  
  MB_DATA.Coils.ConvertionDone |= 1;
}

void PYModule_FillResponse(PCHSens_SensorTypeDef* sensor, Sensor_ResponseStatusTypeDef status)
{
  switch(status)
  {
    // successfull response
    case STATUS_OK:
      // fil with sensor data
      MB_DATA.InRegs.Response.Location = *(uint16_t *)&sensor->sens.hdallas->scratchpad.tHighRegister;
      MB_DATA.InRegs.Response.Config = sensor->sens.hdallas->scratchpad.ConfigRegister;
      MB_DATA.InRegs.Response.ROM[0] = __REV16((sensor->sens.sensROM) & 0xFFFF);
      MB_DATA.InRegs.Response.ROM[1] = __REV16((sensor->sens.sensROM >> 16) & 0xFFFF);
      MB_DATA.InRegs.Response.ROM[2] = __REV16((sensor->sens.sensROM >> 32) & 0xFFFF);
      MB_DATA.InRegs.Response.ROM[3] = __REV16((sensor->sens.sensROM >> 48) & 0xFFFF);
      MB_DATA.InRegs.Response.Status = status;
      break;
    
    case STATUS_SCAN_END:
      MB_DATA.InRegs.Response.Location = 0;
      MB_DATA.InRegs.Response.Config = 0;
      MB_DATA.InRegs.Response.ROM[0] = 0;
      MB_DATA.InRegs.Response.ROM[1] = 0;
      MB_DATA.InRegs.Response.ROM[2] = 0;
      MB_DATA.InRegs.Response.ROM[3] = 0;
      MB_DATA.InRegs.Response.Status = status;
      break;
    
    // error read by location
    case STATUS_ERR_READ_LOCATION:
      // fill only location from holdreg
      MB_DATA.InRegs.Response.Location = MB_DATA.HoldRegs.InitStruct.Location;
      MB_DATA.InRegs.Response.Config = 0;
      MB_DATA.InRegs.Response.ROM[0] = 0;
      MB_DATA.InRegs.Response.ROM[1] = 0;
      MB_DATA.InRegs.Response.ROM[2] = 0;
      MB_DATA.InRegs.Response.ROM[3] = 0;
      MB_DATA.InRegs.Response.Status = status;
      break;
    
    // error read by ROM
    case STATUS_ERR_READ_ROM:
      // fill only ROM from holdreg
      MB_DATA.InRegs.Response.Location = 0;
      MB_DATA.InRegs.Response.Config = 0;
      MB_DATA.InRegs.Response.ROM[0] = MB_DATA.HoldRegs.InitStruct.ROM[0];
      MB_DATA.InRegs.Response.ROM[1] = MB_DATA.HoldRegs.InitStruct.ROM[1];
      MB_DATA.InRegs.Response.ROM[2] = MB_DATA.HoldRegs.InitStruct.ROM[2];
      MB_DATA.InRegs.Response.ROM[3] = MB_DATA.HoldRegs.InitStruct.ROM[3];
      MB_DATA.InRegs.Response.Status = status;
      break;
    
    // error init
    case STATUS_ERR_INIT:
      // fill ROM and location from holdreg
      MB_DATA.InRegs.Response.Location = MB_DATA.HoldRegs.InitStruct.Location;
      MB_DATA.InRegs.Response.Config = 0;
      MB_DATA.InRegs.Response.ROM[0] = MB_DATA.HoldRegs.InitStruct.ROM[0];
      MB_DATA.InRegs.Response.ROM[1] = MB_DATA.HoldRegs.InitStruct.ROM[1];
      MB_DATA.InRegs.Response.ROM[2] = MB_DATA.HoldRegs.InitStruct.ROM[2];
      MB_DATA.InRegs.Response.ROM[3] = MB_DATA.HoldRegs.InitStruct.ROM[3];
      MB_DATA.InRegs.Response.Status = status;
      break;
    
    // error deinit
    case STATUS_ERR_DEINIT:
      // fill with sensor data
      MB_DATA.InRegs.Response.Location = *(uint16_t *)&sensor->sens.hdallas->scratchpad.tHighRegister;
      MB_DATA.InRegs.Response.Config = sensor->sens.hdallas->scratchpad.ConfigRegister;
      MB_DATA.InRegs.Response.ROM[0] = __REV16((sensor->sens.sensROM) & 0xFFFF);
      MB_DATA.InRegs.Response.ROM[1] = __REV16((sensor->sens.sensROM >> 16) & 0xFFFF);
      MB_DATA.InRegs.Response.ROM[2] = __REV16((sensor->sens.sensROM >> 32) & 0xFFFF);
      MB_DATA.InRegs.Response.ROM[3] = __REV16((sensor->sens.sensROM >> 48) & 0xFFFF);
      MB_DATA.InRegs.Response.Status = status;
      break;
    
    // error deinit
    case STATUS_ERR_SCAN:
      // fill with sensor data
      MB_DATA.InRegs.Response.Location = 0;
      MB_DATA.InRegs.Response.Config = 0;
      MB_DATA.InRegs.Response.ROM[0] = __REV16((sensor->sens.sensROM) & 0xFFFF);
      MB_DATA.InRegs.Response.ROM[1] = __REV16((sensor->sens.sensROM >> 16) & 0xFFFF);
      MB_DATA.InRegs.Response.ROM[2] = __REV16((sensor->sens.sensROM >> 32) & 0xFFFF);
      MB_DATA.InRegs.Response.ROM[3] = __REV16((sensor->sens.sensROM >> 48) & 0xFFFF);
      MB_DATA.InRegs.Response.Status = status;
      break;
    
    default:
      MB_DATA.InRegs.Response.Location = 0;
      MB_DATA.InRegs.Response.Config = 0;
      MB_DATA.InRegs.Response.ROM[0] = 0;
      MB_DATA.InRegs.Response.ROM[1] = 0;
      MB_DATA.InRegs.Response.ROM[2] = 0;
      MB_DATA.InRegs.Response.ROM[3] = 0;
      MB_DATA.InRegs.Response.Status = 0;
      break;
  }
}
void PYModule_CheckModuleLosted(PCHSens_ModuleTypeDef *module, uint8_t *losted_flag)
{
  if(module->sens1.not_found)
    *losted_flag |= 1;
  if(module->sens2.not_found)
    *losted_flag |= 1;
  if(module->sens3.not_found)
    *losted_flag |= 1;
  if(module->sens4.not_found)
    *losted_flag |= 1;
}
void PYModule_StoreModuleToModbus(PCHSens_ModuleTypeDef *module)
{
  uint8_t mb_location;
  uint8_t pch_numb = (module->refLocation.param.PCHdig1 - 1)*3 + (module->refLocation.param.PCHdig2 - 1);
  pch_numb *= 4;  
  
  mb_location = pch_numb + module->sens1.Location.param.Location;
  if (mb_location < DS18B20_DEVICE_AMOUNT)
    MB_DATA.InRegs.SensTemperature[mb_location] = module->sens1.sens.temperature*100;
  
  mb_location = pch_numb + module->sens2.Location.param.Location;
  if (mb_location < DS18B20_DEVICE_AMOUNT)
    MB_DATA.InRegs.SensTemperature[mb_location] = module->sens2.sens.temperature*100;
  
  mb_location = pch_numb + module->sens3.Location.param.Location;
  if (mb_location < DS18B20_DEVICE_AMOUNT)
    MB_DATA.InRegs.SensTemperature[mb_location] = module->sens3.sens.temperature*100;
  
  mb_location = pch_numb + module->sens4.Location.param.Location;
  if (mb_location < DS18B20_DEVICE_AMOUNT)
    MB_DATA.InRegs.SensTemperature[mb_location] = module->sens4.sens.temperature*100;
}

