278 lines
8.9 KiB
C
278 lines
8.9 KiB
C
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
|
|
/************************************************************************************
|
|
** **
|
|
** mcHF QRP Transceiver **
|
|
** K Atanassov - M0NKA 2014 **
|
|
** **
|
|
**---------------------------------------------------------------------------------**
|
|
** **
|
|
** File name: **
|
|
** Description: **
|
|
** Last Modified: **
|
|
** Licence: GNU GPLv3 **
|
|
************************************************************************************/
|
|
#ifndef USE_HAL_DRIVER
|
|
#define USE_HAL_DRIVER
|
|
#endif
|
|
#include "uhsdr_board.h"
|
|
#include <stdint.h>
|
|
#include "config_storage.h"
|
|
#include "ui_configuration.h"
|
|
#include "serial_eeprom.h"
|
|
#include "uhsdr_flash.h"
|
|
|
|
static uint8_t config_ramcache[MAX_VAR_ADDR*2+2];
|
|
|
|
|
|
#ifdef USE_CONFIGSTORAGE_FLASH
|
|
void ConfigStorage_CopyFlash2RAMCache()
|
|
{
|
|
uint16_t i, data;
|
|
|
|
config_ramcache[0] = ts.ser_eeprom_type;
|
|
config_ramcache[1] = ts.configstore_in_use;
|
|
for(i=1; i <= MAX_VAR_ADDR; i++)
|
|
{
|
|
Flash_ReadVariable(i, &data);
|
|
config_ramcache[i*2+1] = (uint8_t)((0x00FF)&data);
|
|
data = data>>8;
|
|
config_ramcache[i*2] = (uint8_t)((0x00FF)&data);
|
|
}
|
|
ts.configstore_in_use = CONFIGSTORE_IN_USE_RAMCACHE;
|
|
}
|
|
// copy data from flash storage to serial EEPROM
|
|
void ConfigStorage_CopyFlash2Serial(void)
|
|
{
|
|
ConfigStorage_CopyFlash2RAMCache();
|
|
ConfigStorage_CopyRAMCache2Serial();
|
|
}
|
|
|
|
// copy data from serial to virtual EEPROM
|
|
void ConfigStorage_CopySerial2Flash(void)
|
|
{
|
|
uint16_t count;
|
|
uint16_t data;
|
|
|
|
for(count=1; count <= MAX_VAR_ADDR; count++)
|
|
{
|
|
// SerialEEPROM_ReadVariable(count, &data);
|
|
// Flash_UpdateVariable(count, data);
|
|
if (SerialEEPROM_ReadVariable(count, &data) == HAL_OK)
|
|
{
|
|
Flash_UpdateVariable(count, data);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* verify data serial / virtual EEPROM
|
|
* sets ts.configstore_in_use to CONFIGSTORE_IN_USE_ERROR if
|
|
* it encounters a difference between flash and I2C
|
|
* Used only for debugging
|
|
*/
|
|
static bool ConfigStorage_CheckSameContentSerialAndFlash(void)
|
|
{
|
|
bool retval = true;
|
|
for(uint16_t count=1; retval == true && count <= MAX_VAR_ADDR; count++)
|
|
{
|
|
uint16_t data1, data2;
|
|
// SerialEEPROM_ReadVariable(count, &data1);
|
|
// Flash_ReadVariable(count, &data2);
|
|
// if(data1 != data2)
|
|
if (SerialEEPROM_ReadVariable(count, &data1) == HAL_OK)
|
|
{
|
|
Flash_ReadVariable(count, &data2);
|
|
if(data1 != data2)
|
|
{
|
|
retval = false;
|
|
ts.configstore_in_use = CONFIGSTORE_IN_USE_ERROR; // mark data copy as faulty
|
|
}
|
|
}
|
|
else
|
|
{
|
|
retval = false;
|
|
// ts.configstore_in_use = CONFIGSTORE_IN_USE_ERROR; // mark data copy as faulty
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Interface for all EEPROM (ser/virt) functions and our code
|
|
//
|
|
// if configstore_in_use == 0 write/read to serial EEPROM,
|
|
// if its 0xAA use data in buffer
|
|
// otherwise use virtual EEPROM
|
|
uint16_t ConfigStorage_ReadVariable(uint16_t addr, uint16_t *value)
|
|
{
|
|
uint16_t retval;
|
|
switch(ts.configstore_in_use){
|
|
case CONFIGSTORE_IN_USE_I2C:
|
|
retval = SerialEEPROM_ReadVariable(addr, value);
|
|
break;
|
|
case CONFIGSTORE_IN_USE_FLASH:
|
|
case SER_EEPROM_TOO_SMALL:
|
|
retval = Flash_ReadVariable(addr, value);
|
|
break;
|
|
case CONFIGSTORE_IN_USE_RAMCACHE:
|
|
{
|
|
uint8_t lowbyte;
|
|
uint8_t highbyte;
|
|
uint16_t data;
|
|
|
|
highbyte = config_ramcache[addr*2];
|
|
lowbyte = config_ramcache[addr*2+1];
|
|
data = lowbyte + (highbyte<<8);
|
|
*value = data;
|
|
retval = 0;
|
|
break;
|
|
}
|
|
default:
|
|
retval = 0;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
//*----------------------------------------------------------------------------
|
|
//* Function Name : Write_EEPROM
|
|
//* Object :
|
|
//* Object :
|
|
//* Input Parameters : addr to write to, 16 bit value as data
|
|
//* Output Parameters : returns HAL_OK if OK, otherwise various error codes.
|
|
//* FLASH_ERROR_OPERATION is also returned if eeprom_in_use contains bogus values.
|
|
//* Functions called :
|
|
//*----------------------------------------------------------------------------
|
|
uint16_t ConfigStorage_WriteVariable(uint16_t addr, uint16_t value)
|
|
{
|
|
HAL_StatusTypeDef status = HAL_ERROR;
|
|
if(ts.configstore_in_use == CONFIGSTORE_IN_USE_I2C)
|
|
{
|
|
SerialEEPROM_UpdateVariable(addr, value);
|
|
status = HAL_OK;
|
|
}
|
|
else if(ts.configstore_in_use == CONFIGSTORE_IN_USE_FLASH)
|
|
{
|
|
status = (Flash_UpdateVariable(addr, value));
|
|
}
|
|
else if(ts.configstore_in_use == CONFIGSTORE_IN_USE_RAMCACHE)
|
|
{
|
|
/**
|
|
* Was found that during saving settings,
|
|
* first two cells was corrupted.
|
|
* Just temp. protection...
|
|
*/
|
|
if ( addr == 0 )
|
|
{
|
|
status = HAL_ERROR;
|
|
}
|
|
else
|
|
{
|
|
uint8_t lowbyte;
|
|
uint8_t highbyte;
|
|
|
|
lowbyte = (uint8_t)((0x00FF)&value);
|
|
highbyte = (uint8_t)((0x00FF)&(value >> 8));
|
|
config_ramcache[addr*2] = highbyte;
|
|
config_ramcache[addr*2+1] = lowbyte;
|
|
status = HAL_OK;
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
void ConfigStorage_Init()
|
|
{
|
|
// virtual Eeprom init
|
|
#ifdef USE_CONFIGSTORAGE_FLASH
|
|
ts.ee_init_stat = Flash_Init(); // get status of EEPROM initialization
|
|
#else
|
|
ts.ee_init_stat = HAL_ERROR; // get status of EEPROM initialization
|
|
#endif
|
|
|
|
ts.configstore_in_use = ts.ee_init_stat == HAL_OK? CONFIGSTORE_IN_USE_FLASH: CONFIGSTORE_IN_USE_ERROR;
|
|
// at this point, we have a working flash config storage (or not)
|
|
|
|
ts.ser_eeprom_type = SerialEEPROM_Detect();
|
|
|
|
// incompatible EEPROMs, no EEPROM at all, EEPROM to small
|
|
if(SerialEEPROM_eepromTypeDescs[ts.ser_eeprom_type].supported == true)
|
|
{
|
|
// we read the "in use" signature here, first we use a 16 bit value to keep the error code if any
|
|
// this was report in #857
|
|
uint16_t ser_eeprom_in_use = SerialEEPROM_Get_UseStateInSignature();
|
|
|
|
if(ser_eeprom_in_use == SER_EEPROM_NOT_IN_USE) // empty EEPROM
|
|
{
|
|
|
|
#ifdef USE_CONFIGSTORAGE_FLASH
|
|
// if we have a flash storage available, copy its contents into EEPROM
|
|
if (ts.ee_init_stat == HAL_OK)
|
|
{
|
|
ts.configstore_in_use = CONFIGSTORE_IN_USE_FLASH;
|
|
|
|
ConfigStorage_CopyFlash2Serial(); // copy data from virtual to serial EEPROM
|
|
ConfigStorage_CheckSameContentSerialAndFlash(); // just 4 debug purposes
|
|
}
|
|
#endif
|
|
SerialEEPROM_Set_UseStateInSignature(SER_EEPROM_IN_USE); // serial EEPROM in use now
|
|
}
|
|
else
|
|
{
|
|
// if larger than 255 I2C code reported an error
|
|
if (ser_eeprom_in_use > 0x00ff)
|
|
{
|
|
ts.configstore_in_use = CONFIGSTORE_IN_USE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
ts.configstore_in_use = CONFIGSTORE_IN_USE_I2C;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ConfigStorage_CopySerial2RAMCache()
|
|
{
|
|
SerialEEPROM_24Cxx_ReadBulk(0, config_ramcache, MAX_VAR_ADDR*2+2, ts.ser_eeprom_type);
|
|
|
|
config_ramcache[0] = ts.ser_eeprom_type;
|
|
config_ramcache[1] = ts.configstore_in_use;
|
|
|
|
ts.configstore_in_use = CONFIGSTORE_IN_USE_RAMCACHE;
|
|
}
|
|
|
|
uint16_t ConfigStorage_CopyRAMCache2Serial()
|
|
{
|
|
// we start behind the signature, which we don't want to change
|
|
uint16_t retval = SerialEEPROM_24Cxx_WriteBulk(2, config_ramcache+2, MAX_VAR_ADDR*2, ts.ser_eeprom_type);
|
|
if (retval == HAL_OK)
|
|
{
|
|
ts.configstore_in_use = CONFIGSTORE_IN_USE_I2C;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
//copy array directly to serial EEPROM
|
|
uint16_t ConfigStorage_CopyArray2Serial(uint32_t Addr, const uint8_t *buffer, uint16_t length)
|
|
{
|
|
uint16_t retval = HAL_OK;
|
|
if(ts.configstore_in_use == CONFIGSTORE_IN_USE_I2C)
|
|
{
|
|
retval = SerialEEPROM_24Cxx_WriteBulk(Addr, buffer, length, ts.ser_eeprom_type);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
//read array directly from serial EEPROM
|
|
void ConfigStorage_CopySerial2Array(uint32_t Addr, uint8_t *buffer, uint16_t length)
|
|
{
|
|
if(ts.configstore_in_use == CONFIGSTORE_IN_USE_I2C)
|
|
{
|
|
SerialEEPROM_24Cxx_ReadBulk(Addr, buffer, length, ts.ser_eeprom_type);
|
|
}
|
|
|
|
}
|