/****************************************************************************/
/* Copyright 2012 MBARI							    */
/****************************************************************************/
/* Summary  : UStore I/O Layer for Invensense MotionApps		    */
/* Filename : ustore_cf2.c						    */
/* Author   : Robert Herlien (rah)					    */
/* Project  : Benthic Event Detection System (BEDS)			    */
/* Revision : 1.0							    */
/* Created  : 04/26/2012 by Robert Herlien (rah), MBARI			    */
/*									    */
/* 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:						    */
/* 26apr2012 rah - created						    */
/* $Log$
 */
/****************************************************************************/

#include <mbariTypes.h>			/* MBARI type definitions	    */
#include <mbariConst.h>			/* MBARI constants		    */
#include <beds.h>			/* OASIS controller definitions	    */
#include <io.h>				/* OASIS I/O definitions	    */

#include <cfxbios.h>			/* Persistor BIOS definitions	    */
#include <cfxpico.h>			/* Persistor PicoDOS definitions    */
#include <stdio.h>			/* Standard C library		    */
#include <stdlib.h>			/* Standard C library		    */
#include <string.h>			/* Standard String library	    */

#include <mltypes.h>
#include <ustore_manager_io.h>
#include <ustore_delegate_io.h>
#include <log.h>

typedef	uint16_t	nvram_addr_t;

char	*ustore_fname = "MPU6050.CAL";
FILE	*ustore_fp = NULL;

/*				*/
/* From ustore_nvram_uc3_io.c	*/
/* Modified to use file I/O	*/
/*				*/

#undef MPL_LOG_TAG
#define MPL_LOG_TAG "MPL-ustore-mlsl-io"

#define USTORE_STATE_CLOSED      0
#define USTORE_STATE_STORE_OPEN  1
#define USTORE_STATE_LOAD_OPEN   2

#define STORE_CAL_SIZE 100


/* Don't allow overlapping store and load. 
 * (Just in case of a programming error in
 *  manager or delegate.)
 */
static int state = USTORE_STATE_CLOSED;

/* Buffer used for store and load */
nvram_addr_t cal_data = 0;
nvram_addr_t cal_end;

/* ustore state */
nvram_addr_t pcal;
nvram_addr_t section_end;

inv_error_t inv_ustoreload_set_max_len(int l)
{
    if (state == USTORE_STATE_CLOSED)
        return INV_ERROR;

    if (pcal + l <= cal_end){
        section_end = pcal + l;
        return INV_SUCCESS;
    } else {
        return INV_ERROR_MEMORY_EXAUSTED;
    }

}

void inv_ustoreload_reset_len(void)
{
    section_end = 0;
}

/* ------------- S T O R E - R O U T I N E S ------- */

inv_error_t inv_ustore_open(void)
{
    if (state != USTORE_STATE_CLOSED)
        return INV_ERROR;
    pcal = cal_data;
    section_end = 0;
    cal_end = cal_data + STORE_CAL_SIZE;
    state = USTORE_STATE_STORE_OPEN;

    if ((ustore_fp = fopen(ustore_fname, "w")) == NULL)
	return(INV_ERROR);

    MPL_LOGD("inv_ustore_open() returns success\n");
    return INV_SUCCESS;
}

inv_error_t inv_ustore_close(void)
{
    inv_error_t result = INV_SUCCESS;
    if (state != USTORE_STATE_STORE_OPEN)
        return INV_ERROR;
    section_end = 0;
    cal_end = 0;
    state = USTORE_STATE_CLOSED;
    if (ustore_fp != NULL)
	fclose(ustore_fp);
    ustore_fp = NULL;
    return result;
}

inv_error_t inv_ustore_byte(unsigned char b)
{
    return inv_ustore_mem((const void *)&b, 1);
}

inv_error_t inv_ustore_mem(const void *b, int length)
{
    if (state != USTORE_STATE_STORE_OPEN)
        return INV_ERROR;
    if ((section_end != 0) && 
        ((pcal + length) > section_end))
        return INV_ERROR_MEMORY_EXAUSTED;

    if (pcal + length >= cal_end)
        return INV_ERROR_MEMORY_EXAUSTED;

    if (ustore_fp == NULL)
	return(INV_ERROR);
    else
	fwrite(b, length, 1, ustore_fp);
    pcal += length;
    return INV_SUCCESS;
}

/* ------------- L O A D - R O U T I N E S ------- */

inv_error_t inv_uload_open(void)
{
    unsigned int store_length;
    unsigned char dataLen[4];
    MPL_LOGD("inv_uload_open()\n");
    if (state != USTORE_STATE_CLOSED)
        return INV_ERROR;

    MPL_LOGD("inv_uload_open() opening %s\n", ustore_fname);
    if ((ustore_fp = fopen(ustore_fname, "r")) == NULL)
    {
	MPL_LOGD("inv_uload_open() returning INV_ERROR\n");
	return(INV_ERROR);
    }

    MPL_LOGD("inv_uload_open() reading cal file\n");
    if (fread(dataLen, 4, 1, ustore_fp) < 1)
	return(INV_ERROR);

    store_length = dataLen[3];
    if (store_length > STORE_CAL_SIZE)
        return INV_ERROR_MEMORY_EXAUSTED;
    MPL_LOGD("Calibration data length is : %d\n", dataLen[3]);

    pcal = cal_data + 4;
    cal_end = cal_data + STORE_CAL_SIZE;
    section_end = 0;
    state = USTORE_STATE_LOAD_OPEN;
    MPL_LOGD("inv_load_open() returns success\n");
    return INV_SUCCESS;
}

inv_error_t inv_uload_close(void)
{
    if (state != USTORE_STATE_LOAD_OPEN)
        return INV_ERROR;

    section_end = 0;
    cal_end = 0;

    if (ustore_fp != NULL)
	fclose(ustore_fp);
    ustore_fp = NULL;
    state = USTORE_STATE_CLOSED;
    return INV_SUCCESS;
}


inv_error_t inv_uload_byte(unsigned char *b)
{
    return inv_uload_mem(b, 1);
}

inv_error_t inv_uload_mem(void *b, int length)
{
    if (state != USTORE_STATE_LOAD_OPEN)
        return INV_ERROR;
    if (section_end != 0 &&
    (pcal + length) > section_end)
        return INV_ERROR_MEMORY_EXAUSTED;
    if (pcal + length >= cal_end)
        return INV_ERROR_MEMORY_EXAUSTED;

    if (ustore_fp == NULL)
	return(INV_ERROR);
    else
	fread(b, length, 1, ustore_fp);

    pcal += length;
    return INV_SUCCESS;
}

inv_error_t inv_clear_nvram(void)
{
    unsigned char clearData[99];
    inv_error_t result = INV_SUCCESS;
    memset(clearData, 0, sizeof(clearData));
    result = inv_ustore_open();
    if (result != INV_SUCCESS){
        LOG_RESULT_LOCATION(result);
        return result;
    }
    result = inv_ustore_mem(clearData, sizeof(clearData));
    if (result != INV_SUCCESS) {
        LOG_RESULT_LOCATION(result);
        return result;
    }
    result = inv_ustore_close();
    if (result != INV_SUCCESS) {
        LOG_RESULT_LOCATION(result);
        return result;
    }
    return INV_SUCCESS;
}

/* ustore_cf2.c */
