/****************************************************************************/
/* Copyright 2015 MBARI                                                     */
/****************************************************************************/
/* Summary  : Non-volatile Configuration Routines for OASIS5                */
/* Filename : config.c                                                      */
/* Author   : Robert Herlien (rah)                                          */
/* Project  : OASIS Mooring Replacement (OASIS5)                            */
/* Revision: 1.0                                                            */
/* Created  : 10/29/2015                                                    */
/*                                                                          */
/* MBARI provides this documentation and code "as is", with no warranty,    */
/* express or implied, of its quality or consistency. It is provided without*/
/* support and without obligation on the part of the Monterey Bay Aquarium  */
/* Research Institute to assist in its use, correction, modification, or    */
/* enhancement. This information should not be published or distributed to  */
/* third parties without specific written permission from MBARI.            */
/*                                                                          */
/****************************************************************************/
/* Modification History:                                                    */
/* Written by Mike Risi for Respirometer project in 2009                    */
/* Modified by Bob Herlien for SensorNode for xFOCE, May 2013               */
/* Modified by Bob Herlien for OASIS5, 29oct2015                            */
/****************************************************************************/

#include "config.h"
#include "flash_mem.h"
#include <string.h>

typedef struct
{
    ConfigData config;
    unsigned int checksum;
} ConfigBlock;

unsigned int calcCheckSum(char* buff, int size);


/****************************************************************************/
/*                             Config functions                             */
/****************************************************************************/
int cfgCheck(ConfigData* config)
{
    /* check the id */
    if ( (config->id < 1) || (config->id > 247) )
        return(-1);
    
    /* check the baud */
    switch ( config->baud )
    {
        case 19200: break;
        case 38400: break;
        case 57600: break;
        case 115200: break;
        default: return(-1);
    }

    return 0;
}

int cfgRead(ConfigData* config)
{
    ConfigBlock cb;
    unsigned int cs_calc;

    /* read the configuation struct from memory */
    memRead((char*)&cb, sizeof(cb));

    cs_calc = calcCheckSum((char*)&cb.config, sizeof(ConfigData));

    if ( cs_calc != cb.checksum )
        return -1;
    
    /* assign stored data to the config data struct */
    memcpy(config, &cb, sizeof(ConfigData));

    return cfgCheck(config);
}

int cfgWrite(ConfigData* config)
{
    ConfigBlock cb;
    
    /* if config params are not in a valid range, don't write it */
    if ( cfgCheck(config) != 0 )
        return -1;
    
    /* assign stored data to the config data struct */
    memcpy(&cb, config, sizeof(ConfigData));

    /* calc and assign the checksum */
    cb.checksum = calcCheckSum((char*)&cb.config, sizeof(ConfigData));

    /* erase the old config */
    memErase();

    /* write the new config */
    memWrite((char*)&cb, sizeof(cb));
    
    return 0;
}

int cfgSetBootFlag()
{
    ConfigBlock cb;

    memset(&cb, 0, sizeof(ConfigBlock));
    /* set the boot flag */
    cb.config.id = BOOTLOADER_FLAG;

    /* calc and assign the checksum */
    cb.checksum = calcCheckSum((char*)&cb.config, sizeof(ConfigData));

    /* erase the old config */
    memErase();

    /* write the new config */
    memWrite((char*)&cb, sizeof(cb));
    
    return 0;
}


unsigned int calcCheckSum(char* buff, int size)
{
    int i;
    unsigned int cs = 0;

    for (i = 0; i < size; i++)
        cs += buff[i];

    return cs;
}
