/*
 * milandr.cpp
 *
 *  Created on: 30 нояб. 2018 г.
 *      Author: alexrayne <alexraynepe196@gmail.com>
  ------------------------------------------------------------------------
    Copyright (c) alexrayne

   All rights reserved.
   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
   - Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
   - Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the distribution.
   - Neither the name of ARM nor the names of its contributors may be used
     to endorse or promote products derived from this software without
     specific prior written permission.
   *
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE. *
 */

#include <c_compat.h>
#include <string.h>
#include "1636RR52.hpp"
#include <OsSync.h>
#include <trace_probes.h>

#ifndef trace_ssp_wr
trace_need(ssp_wr)
trace_need(ssp_rd)
#endif

//static
const FLASH_1636RR52::ID_t   FLASH_1636RR52::ID_1636RR52 = {
                                      FLASH_1636RR52::idMILANDR
                                    , FLASH_1636RR52::id1636RR52
                                };
//static
const FLASH_1636RR52::Describe   FLASH_1636RR52::info_1636RR52 = {
      struct_field(nb_sectors)          2
    , struct_field(nb_pages_in_sector)  0x10000
    , struct_field(page_size)           1
    , struct_field(burn_page_ticks)     (FLASH_1636RR52::toSPIN*10 + FLASH_1636RR52::toYIELD*4)
    , struct_field(erase_ticks)         OSTicksMS(55)
    , struct_field(erase_all_ticks)     OSTicksMS(110)
};


FLASH_1636RR52::FLASH_1636RR52(dev_name name)
: inherited(name)
{
    assign_info( &info_1636RR52 );
    mode(mode_default_8bit);
    style(addr3BYTE | addrLE);
}

//virtual
int FLASH_1636RR52::init(){
    //return inherited::init();
    // РР52 использует стандартный 8битный обмен с защелкиванием по фронту
    mode(mode_default_8bit);
    style(addr3BYTE | addrLE);
    return DEV_OK;
};

//virtual
int FLASH_1636RR52::deinit(){
    return inherited::deinit();
}

// bound - начальная подготовка флеши к работе, сверка ID, и параметров
//virtual
DevResult FLASH_1636RR52::bind(){
    ID_t    id;
    cs_hold(true);
    trace_ssp_wr_on();
    DevResult ok = postByte(CMD_RDID);
    trace_ssp_wr_off();
    trace_ssp_rd_on();
    cs_hold(false);
    ok = readData(id.raw, id.idLEN);
    trace_ssp_rd_off();
    if (ok != id.idLEN)
        return ok;
    ok = memcmp(id.raw, ID_1636RR52.raw, id.idLEN);
    if (ok == 0)
        return DEV_OK;
    return DEV_NO_SUPPORT_ID_ERR;

}

//virtual
DevResult FLASH_1636RR52::read(unsigned page, void* dst, unsigned len){
    return io_ASDEVRESULT( inherited::readData(CMD_READ, page, dst, len), len );
    // if Flash is per-byte writing (pagesie ==1), then suppose that it can
    //      continue read though all chip

    cs_hold(true);
    int ok = write_cmdadress4(CMD_FAST_READ, page);
    cs_hold(false);
    if (ok != 5)
        return ok;

    return io_ASDEVRESULT( ioData(dst, NULL, len), len);
}




DevResult FLASH_1636RR52::protect_sector(unsigned page, bool onoff){
    if (!is_WEL())
        return DEV_WRITE_DISABLED_ERR;

    const unsigned cmd = (onoff)? CMD_SEC_PROTECT : CMD_SEC_UNPROTECT;

    enable_wr();
    cs_hold(false);
    int sent = write_cmdadress(cmd, page);
    if (sent != 4)
        return DEV_NOK;

    return DEV_OK;

    // этот для того чтобы убедиться в том что результат операции ожидаемый
    int st = state();
    if (!is_ready(st))
        return DEV_NOK;

    unsigned protection_status = 0;
    DevResult ok = readData(CMD_SEC_PROTECT_STATE, page, &protection_status, 1);
    bool state_protected = (protection_status == psPROTECTED);
    return (state_protected == onoff)? DEV_OK : DEV_NOK;
}

//virtual
PTResult FLASH_1636RR52::protect_sectors(unsigned page, unsigned len, bool onoff){
    if (len <= sec_size())
        return AS_PTRESULT( protect_sector(page, onoff) );

    PTResult res;
    struct pt* pt = &oppt;

    PT_BEGIN(pt)

    cycle_sectors( NULL , page, len);
    {
    sec_op op = (sec_op) ( (onoff)? &FLASH_1636RR52::protect_sec : &FLASH_1636RR52::unprotect_sec );
    cycle_op(op, info().burn_page_ticks);
    }

    PT_SCHEDULE_RESULT_WHILE( pt, res, cycles() );
    PT_RESULT(pt, res);

    PT_END(pt)
}

DevResult FLASH_1636RR52::protect_sec(void* dst, addr_t page, unsigned len){
    return protect_sector(page, true);
}

DevResult FLASH_1636RR52::unprotect_sec(void* dst, addr_t page, unsigned len){
    return protect_sector(page, false);
}



