/**
 * *************************************************************************************************************
 * @file Eeprom.c
 * @author BH_CodeGenerator
 * @version 0.1
 * @date 2022-04-01
 * @warning <!--auto generated by Tools, do not modify or add anything, otherwise, your change will be lost!!! -->
 * @brief all the functions prototypes for Eeprom firmware library
 * MCU / CFG Ver. :BH66F2475/1.7
 * Version = 1.0.0

 * *************************************************************************************************************
 *  @attention
 *
 *  Firmware Disclaimer Information
 *
 *  1. The customer hereby acknowledges and agrees that the program technical documentation, including the
 *     code, which is supplied by BEST HEALTH ELECTRONIC Inc., (hereinafter referred to as BestHealth) is the
 *     proprietary and confidential intellectual property of BestHealth, and is protected by copyright law and
 *     other intellectual property laws.
 *
 *  2. The customer hereby acknowledges and agrees that the program technical documentation, including the
 *     code, is confidential information belonging to BestHealth, and must not be disclosed to any third parties
 *     other than BestHealth and the customer.
 *
 *  3. The program technical documentation, including the code, is provided and for customer reference
 *     only. After delivery by BestHealth, the customer shall use the program technical documentation, including
 *     the code, at their own risk. BestHealth disclaims any expressed, implied or statutory warranties, including
 *     the warranties of merchantability, satisfactory quality and fitness for a particular purpose.
 *
 *  <h2><center>Copyright (C) BEST HEALTH ELECTRONIC Inc. All rights reserved</center></h2>
 */
#include "Eeprom.h"
#include "BH66F2455.h"

#define WORD_LO(w) ((uint8_t)(w & 0xff))
#define WORD_HI(w) ((uint8_t)(w >> 8))

#define EEPROM_ADDRESS_MAX 2048

/**
 * @brief read data to EEPROM
 *
 * @param startAddr start address
 * @param data read data
 * @return true success
 * @return false fail
 */
bool Eeprom_ReadByte(uint16_t addr, uint8_t *data)
{
    if (addr > EEPROM_ADDRESS_MAX)
    {
        return false;
    }
    else
    {
        _eeal = WORD_LO(addr);
        _eeah = WORD_HI(addr);
        _mp1h = 1;
        _mp1l = 0x40;
        asm("set [0x02].1");    // RDEN
        asm("set [0x02].0");    // RD
        asm("sz  [0x02].0");    // RD
        asm("jmp $-1");
        _iar1 = 0;
        *data = _eed;
        return true;
    }
}

/**
 * @brief read data to EEPROM
 *
 * @param startAddr start address
 * @param buf read data
 * @param len read length
 * @return true success
 * @return false fail
 */
bool Eeprom_ReadBuff(uint16_t startAddr, uint8_t *buf, uint16_t len)
{
    if ((startAddr + len) > EEPROM_ADDRESS_MAX)
    {
        return false;
    }
    uint8_t i = 0;
    for (i = 0; i < len; i++)
    {
        if (!Eeprom_ReadByte(startAddr, buf))
        {
            return false;
        }
        startAddr++;
        buf++;
    }
    return true;
}

/**
 * @brief write data to EEPROM
 * @note wren and wr must be written in two consecutive commands
 * so the interrupt must be turned off.
 *
 * @param startAddr start address
 * @param data write data
 * @return true success
 * @return false fail
 */
bool Eeprom_WriteByte(uint16_t startAddr, uint8_t data)
{
    if (startAddr >= EEPROM_ADDRESS_MAX)
    {
        return false;
    }
    else
    {
        bool EMI_Protect = _emi;

        _emi  = 0;
        _mp1h = 1;
        _mp1l = 0x40;
        _eeal = WORD_LO(startAddr);
        _eeah = WORD_HI(startAddr);
        _eed  = data;
        // wren and wr must be written in two consecutive commands
        asm("set [0x02].3");    // WREN
        asm("set [0x02].2");    // WR
        asm("sz  [0x02].2");    // WR
        asm("jmp $-1");
        _iar1 = 0;    // disable WREN
        _emi  = EMI_Protect;
        uint8_t readData;
        if (Eeprom_ReadByte(startAddr, &readData) && readData == data)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

/**
 * @brief write data to EEPROM
 *
 * @param startAddr start address
 * @param buf write data
 * @param len write length
 * @return true success
 * @return false fail
 */
bool Eeprom_WriteBuf(uint16_t startAddr, uint8_t *buf, uint16_t len)
{
    if ((startAddr + len) >= EEPROM_ADDRESS_MAX)
    {
        return false;
    }
    uint8_t i = 0;
    for (i = 0; i < len; i++)
    {
        if (!Eeprom_WriteByte(startAddr, *buf))
        {
            return false;
        }
        startAddr++;
        buf++;
    }
    return true;
}