/*                                              -*- mode:C++; fill-column:100 -*-
  SFBEeprom.cpp - Support for I/O with the EEPROM - common routines
  Copyright (C) 2009 The Regents of the University of New Mexico.  All rights reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library 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
  Lesser General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
  USA
*/

#include "SFBEeprom.h"
#include "SFBConstants.h"       // For LOW, etc
#include "SFBPins.h"            // For BODY_EEPROM_SSEL1_PIN, etc
#include "SFBWiring.h"          // For digitalWrite, etc
#include "SFBAssert.h"          // For API_ASSERT_MAX, etc

SFBEeprom EEPROM IN_BODYRAM_BSS; 

// The platform-specific implementation routines that must be provided
extern void eepromWaitImpl(bool busyWait);
extern void eeprom_startup_initializationImpl();
extern void eepromWriteImpl(u32 addr, const u8 * dataSrc, u32 length, bool busyWait); 
extern void eepromReadImpl(u32 addr, u8 * dataDest, u32 length);

void eeprom_startup_initialization() {
  eeprom_startup_initializationImpl(); // Just defer to platform-specific routine
}

void eepromWait(bool busyWait) {
  eepromWaitImpl(busyWait);
}

void eepromWrite(u32 addr, const u8 * dataSrc, u32 length) {
  API_ASSERT_MAX_CODE(addr+length,eepromSize(),E_API_EEPROM_ADDRESS);
  API_ASSERT_NONNULL(dataSrc);

  eepromWriteImpl(addr,dataSrc,length,false);
}

void eepromWriteReserved(const u32 addr, const u8 * dataSrc, const u32 length) {
  API_ASSERT_NONNULL(dataSrc);
  API_ASSERT_MAX_CODE(addr+length,EEPROM_RESERVED_BYTES+1,E_API_EEPROM_ADDRESS);

  eepromWriteImpl(eepromSize()+addr,dataSrc, length, true);
}

void eepromRead(u32 addr, u8 * dataDest, u32 length) {
  API_ASSERT_MAX_CODE(addr+length,eepromSize()+1,E_API_EEPROM_ADDRESS);
  API_ASSERT_NONNULL(dataDest);
  eepromReadImpl(addr,dataDest,length);
}

void eepromReadReserved(const u32 addr, u8 * dataDest,const u32 length) {
  API_ASSERT_NONNULL(dataDest);
  API_ASSERT_MAX(addr+length,EEPROM_RESERVED_BYTES+1);
  eepromReadImpl(eepromSize()+addr, dataDest, length);
}

u32 eepromSize() {
  return EEPROM_SIZE_BYTES-EEPROM_RESERVED_BYTES;
}
