141 lines
3.3 KiB
C
141 lines
3.3 KiB
C
|
/* Reflow Oven Controller
|
||
|
*
|
||
|
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
|
||
|
*
|
||
|
* This file is part of the Reflow Oven Controller Project.
|
||
|
*
|
||
|
* The reflow oven controller is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License version 2 as
|
||
|
* published by the Free Software Foundation.
|
||
|
*
|
||
|
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with the reflow oven controller project.
|
||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#include <reflow-controller/settings/settings-eeprom.h>
|
||
|
#include <reflow-controller/settings/spi-eeprom.h>
|
||
|
#include <stm-periph/crc-unit.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#define EEPROM_HEADER_MAGIC 0xA5
|
||
|
#define EEPROM_HEADER_COMP_VER 0xFF
|
||
|
|
||
|
static const uint8_t expected_header[2] = {EEPROM_HEADER_MAGIC, EEPROM_HEADER_COMP_VER};
|
||
|
|
||
|
#define EEPROM_CALIBRATION_BASE_ADDR 0x2
|
||
|
struct eeprom_calibration_settings {
|
||
|
uint32_t active;
|
||
|
float offset;
|
||
|
float sens_dev;
|
||
|
uint32_t crc;
|
||
|
};
|
||
|
|
||
|
static bool check_eeprom_header(void)
|
||
|
{
|
||
|
uint8_t header[2] = {0};
|
||
|
|
||
|
/* Try to read the magic header and the compatible version */
|
||
|
spi_eeprom_read(0x0, header, 2);
|
||
|
if (memcmp(header, expected_header, 2))
|
||
|
return false;
|
||
|
else
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static void settings_eeprom_zero()
|
||
|
{
|
||
|
settings_eeprom_save_calibration(0.0f, 0.0f, false);
|
||
|
}
|
||
|
|
||
|
bool settings_eeprom_detect_and_prepare(void)
|
||
|
{
|
||
|
bool eeprom_ready = false;;
|
||
|
|
||
|
int res;
|
||
|
|
||
|
crc_unit_init();
|
||
|
res = spi_eeprom_init();
|
||
|
if (res)
|
||
|
goto ret_deinit_crc;
|
||
|
|
||
|
if (!spi_eeprom_check_connected())
|
||
|
goto ret_deinit_crc;
|
||
|
|
||
|
if (check_eeprom_header() == false) {
|
||
|
/* Try to write a new header and check it again */
|
||
|
spi_eeprom_write(0, expected_header, sizeof(expected_header));
|
||
|
while (spi_eeprom_write_in_progress());
|
||
|
if (check_eeprom_header() == false) {
|
||
|
goto ret_deinit_crc;
|
||
|
} else {
|
||
|
/* Sucessfully written new header
|
||
|
* Zero out the rest of the settings
|
||
|
*/
|
||
|
settings_eeprom_zero();
|
||
|
eeprom_ready = true;
|
||
|
}
|
||
|
} else {
|
||
|
eeprom_ready = true;
|
||
|
}
|
||
|
|
||
|
goto exit;
|
||
|
|
||
|
ret_deinit_crc:
|
||
|
crc_unit_deinit();
|
||
|
|
||
|
exit:
|
||
|
return eeprom_ready;
|
||
|
}
|
||
|
|
||
|
int settings_eeprom_save_calibration(float sens, float offset, bool active)
|
||
|
{
|
||
|
int res;
|
||
|
|
||
|
struct eeprom_calibration_settings sett;
|
||
|
|
||
|
sett.active = (active ? 0xAABBCCDD : 0);
|
||
|
sett.offset = offset;
|
||
|
sett.sens_dev = sens;
|
||
|
|
||
|
crc_unit_reset();
|
||
|
crc_unit_input_array((const uint32_t *)&sett, (sizeof(sett) / 4)-1);
|
||
|
sett.crc = crc_unit_get_crc();
|
||
|
|
||
|
res = spi_eeprom_write(EEPROM_CALIBRATION_BASE_ADDR, (uint8_t *)&sett, sizeof(sett));
|
||
|
|
||
|
if (res)
|
||
|
return -2;
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int settings_eeprom_load_calibration(float *sens, float *offset, bool *active)
|
||
|
{
|
||
|
struct eeprom_calibration_settings sett;
|
||
|
int res;
|
||
|
|
||
|
res = spi_eeprom_read(EEPROM_CALIBRATION_BASE_ADDR, (uint8_t *)&sett, sizeof(sett));
|
||
|
if (res)
|
||
|
return -2;
|
||
|
|
||
|
crc_unit_reset();
|
||
|
crc_unit_input_array((const uint32_t *)&sett, sizeof(sett) / 4 - 1);
|
||
|
if (crc_unit_get_crc() == sett.crc) {
|
||
|
if (sens)
|
||
|
*sens = sett.sens_dev;
|
||
|
if (offset)
|
||
|
*offset = sett.offset;
|
||
|
if (active)
|
||
|
*active = (sett.active ? true : false);
|
||
|
return 0;
|
||
|
} else {
|
||
|
return -1;
|
||
|
}
|
||
|
}
|