195 lines
4.8 KiB
C
195 lines
4.8 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 0xC5
|
|
#define EEPROM_HEADER_COMP_VER 0x01
|
|
|
|
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;
|
|
};
|
|
|
|
#define EEPROM_OVER_TEMP_CONFIG_BASE_ADDR (EEPROM_CALIBRATION_BASE_ADDR + sizeof(struct eeprom_calibration_settings))
|
|
|
|
struct eeprom_over_temp_config {
|
|
float over_temperature;
|
|
uint32_t over_temp_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(void)
|
|
{
|
|
settings_eeprom_save_calibration(0.0f, 0.0f, false);
|
|
settings_eeprom_save_overtemp_limit(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;
|
|
}
|
|
}
|
|
|
|
int settings_eeprom_save_overtemp_limit(float overtemp_limit, bool active)
|
|
{
|
|
int res;
|
|
struct eeprom_over_temp_config over_temp_conf_entry;
|
|
const uint8_t zero_vals[sizeof(over_temp_conf_entry)] = {0};
|
|
|
|
if (!active) {
|
|
res = spi_eeprom_write(EEPROM_OVER_TEMP_CONFIG_BASE_ADDR, (const uint8_t *)zero_vals,
|
|
sizeof(zero_vals));
|
|
return res ? -1 : 0;
|
|
}
|
|
|
|
over_temp_conf_entry.over_temperature = overtemp_limit;
|
|
crc_unit_reset();
|
|
crc_unit_input_array((uint32_t *)&over_temp_conf_entry, 1);
|
|
over_temp_conf_entry.over_temp_crc = crc_unit_get_crc();
|
|
res = spi_eeprom_write(EEPROM_OVER_TEMP_CONFIG_BASE_ADDR, (const uint8_t *)&over_temp_conf_entry,
|
|
sizeof(over_temp_conf_entry));
|
|
|
|
return res ? -1 : 0;
|
|
}
|
|
|
|
int settings_eeprom_load_overtemp_limit(float *overtemp_limit)
|
|
{
|
|
int res;
|
|
struct eeprom_over_temp_config over_temp_conf_entry;
|
|
|
|
if (!overtemp_limit)
|
|
return -1001;
|
|
res = spi_eeprom_read(EEPROM_OVER_TEMP_CONFIG_BASE_ADDR, (uint8_t *)&over_temp_conf_entry,
|
|
sizeof(struct eeprom_over_temp_config));
|
|
if (res)
|
|
return -2;
|
|
|
|
crc_unit_reset();
|
|
crc_unit_input_array((uint32_t *)&over_temp_conf_entry, 1);
|
|
if (crc_unit_get_crc() != over_temp_conf_entry.over_temp_crc)
|
|
return -1;
|
|
|
|
*overtemp_limit = over_temp_conf_entry.over_temperature;
|
|
return 0;
|
|
}
|