/*
 * i2c_fram.c
 *
 *  Created on: Aug 5, 2019
 *      Author: tm
 */

#include <stdint.h>
#include <stdbool.h>
#include "main.h"
#include "system.h"
#include "user_io.h"
#include "uartstdio.h"  // User local version with larger RX buffer
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"

#include "i2c0.h"
#include "i2c_fram.h"
#include "apf.h"
#include "apf_util.h"
#include "apf_init.h"
#include "serial_cmd_fxn.h"
#include "board_util.h"


unsigned char framBuf[132];

#define I2C_FRAM_ADDR   0x50       // 0xA0/2 and bit.0 is the 256 byte page address - the i2c API's take care of stuffing the R/W* bit

#if BOARD_MFET >= 2 || BOARD_MPHOX >= 1  || BOARD_MSC == 1
#define FRAM_FM24CL04B  1
#define FRAM_MB85RC1M   0
#endif

#if BOARD_NANOFET == 1 || BOARD_MSC == 3
#define FRAM_FM24CL04B  0
#define FRAM_MB85RC1M   1
#endif

uint32_t fram_apf_vars_retrievedFlg = 0;
uint32_t fram_apfArray_retrievedFlg = 0;

// check for existence, return 1 if OK
int fram_init(void)
{
    uint32_t id = 0;
    int ret     = 0;

    // read the manufacturer id, or read byte signature in the case of no manufactuerer id
    ret = fram_probe(&id);
    if( (ret <=0) || (id != 0xAA55AA55) )
    {
        uprintf("\r\nERROR: FRAM fails probe, do not deploy until resolved\r\n");
        return 0;
    }

    return 1;
}



int fram_sys_samp_store(void)
{
    wdog_pet();
    return i2c0_fram_write(I2C_FRAM_ADDR, (unsigned char *)&sys_samp, sizeof(sys_samp), FRAM_SYSSAMP_ADDR);     // 64
}

int fram_sys_samp_retrieve(void)
{
    wdog_pet();
    return i2c0_fram_read(I2C_FRAM_ADDR, (unsigned char *)&sys_samp, sizeof(sys_samp), FRAM_SYSSAMP_ADDR);
}

//----------------------------------------------------
// for pH, APFTODO, make a better API
int fram_last_samp_store(void)
{
    wdog_pet();
    return i2c0_fram_write(I2C_FRAM_ADDR, (unsigned char *)&sampl, sizeof(sampl), FRAM_LASTSAMP_ADDR);     // 64
}

int fram_last_samp_retrieve(void)
{
    wdog_pet();
    return i2c0_fram_read(I2C_FRAM_ADDR, (unsigned char *)&sampl, sizeof(sampl), FRAM_LASTSAMP_ADDR);
}

//----------------------------------------------------
//void fram_apf_vars_store(unsigned char *apfBuf, uint32_t byteCnt)
int fram_apf_vars_store(void)  //APFTODO, rename to fram_apfcfg_store();
{
    wdog_pet();

    int ret = i2c0_fram_write(I2C_FRAM_ADDR, (unsigned char *)&apf_fram, sizeof(apf_fram), FRAM_APFVAR_ADDR);     // FRAM_APFVAR_ADDR starts at ADDR=256 (see defs above)
    if(ret > 0)
    {
        fram_apf_vars_retrievedFlg = 1;
    }
    else
    {
        fram_apf_vars_retrievedFlg = 0;
    }

    return ret;
}

//void fram_apf_vars_retrieve(unsigned char *apfBuf, uint32_t byteCnt)
int fram_apf_vars_retrieve(void)        //APFTODO, rename to fram_apfcfg_retrieve();
{
    wdog_pet();

    int ret = i2c0_fram_read(I2C_FRAM_ADDR, (unsigned char *)&apf_fram, sizeof(apf_fram), FRAM_APFVAR_ADDR);
    if(ret > 0)
    {
        fram_apf_vars_retrievedFlg = 1;
    }
    else
    {
        fram_apf_vars_retrievedFlg = 0;
    }

    return ret;
}

int fram_apf_vars_refresh(void)
{
    wdog_pet();
    if(fram_apf_vars_retrievedFlg != 1)
    {
        //uprintf("DBG fram_apf_vars_retrieve"); prn_nl();
        fram_apf_vars_retrieve();  //fram_apf_vars_retrievedFlg=1
    }

    return(fram_apf_vars_retrievedFlg);
}

//--------------- apfArray is ecoefszer.cal in FRAM ---------
int fram_apfArray_refresh(void)
{
    wdog_pet();
    if(fram_apfArray_retrievedFlg != 1)
    {
        fram_apfArray_retrieve();         // fram_apfArray_retrievedFlg = 1;
    }

    //apf_ecoef_print();      //DBG
    //apf_zcoef_print();

    return(fram_apfArray_retrievedFlg);

}

//void fram_apf_vars_retrieve(unsigned char *apfBuf, uint32_t byteCnt)
// ret 1 if good
// ret 0 on fail
int fram_apfArray_retrieve(void)
{

    wdog_pet();

    int ret = i2c0_fram_read(I2C_FRAM_ADDR, (unsigned char *)&apfArray, sizeof(apfArray), FRAM_APFARRAY_ADDR);
    if(ret > 0)
    {
        apf_copyEcoefsFileToData();         // populate global var used in NO3 calc
        fram_apfArray_retrievedFlg = 1;

    }
    else
    {
        fram_apfArray_retrievedFlg = 0;
    }

    return ret;
}

//void fram_apf_vars_store(unsigned char *apfBuf, uint32_t byteCnt)
int fram_apfArray_store(void)
{
    //uprintf("DBG: fram_apfArray_store"); prn_nl();
    //apf_zcoef_print();
    //wait_consoleTx();
    wdog_pet();

    int ret = i2c0_fram_write(I2C_FRAM_ADDR, (unsigned char *)&apfArray, sizeof(apfArray), FRAM_APFARRAY_ADDR);     // FRAM_APFVAR_ADDR starts at ADDR=256 (see defs above)
    if(ret > 0)
    {
        fram_apfArray_retrievedFlg = 1;
    }
    else
    {
        fram_apfArray_retrievedFlg = 0;
    }

    return ret;
}

//-----------------------------------------------------------

// used for SL command in APF
int fram_apf_dbuf_store(unsigned char *sampBuf, uint32_t byteCnt)
{
    wdog_pet();
    //uprintf("fram_apf_dbuf_store incomplete type is not allowed"); prn_nl();
    //i2c0_fram_write(I2C_FRAM_ADDR, (unsigned char *)&apf_dbuf, sizeof(apf_dbuf), FRAM_APFDBUF_ADDR);     // 
    return i2c0_fram_write(I2C_FRAM_ADDR, (unsigned char *)sampBuf, byteCnt, FRAM_APFDBUF_ADDR);
}

int fram_apf_dbuf_retrieve(unsigned char *sampBuf, uint32_t byteCnt)
{
    wdog_pet();
    //uprintf("fram_apf_dbuf_retrieve incomplete type is not allowed"); prn_nl();
    //i2c0_fram_read(I2C_FRAM_ADDR, (unsigned char *)&apf_dbuf, sizeof(apf_dbuf), FRAM_APFDBUF_ADDR, TRUE);
    return i2c0_fram_read(I2C_FRAM_ADDR, (unsigned char *)sampBuf, byteCnt, FRAM_APFDBUF_ADDR);
}

/******************************************************************************
 * Write multiple bytes to a slave device
 *
 * Parameters:
 *  uiSlave_addr : the slave address
 *  *ucData    : the data that are going to be sent
 *  uiCount    : number of bytes to be written
 *  ucStart_addr : starting register address you want to write or a control byte
 *
 * Return: none
 * Useful info:  https://github.com/sosandroid/FRAM_MB85RC_I2C
 *****************************************************************************/
int i2c0_fram_write(unsigned char uiSlave_addr, unsigned char *ucData, uint16_t uiCount, uint16_t ucStart_addr)  //void i2c0_write(unsigned char uiSlave_add, unsigned char *ucData, uint16_t uiCount, unsigned char ucStart_add)
{
    int ret;
    unsigned char i2c_addr;
    uint8_t addr_buf[2];

#if FRAM_FM24CL04B == 1
    i2c_addr = (uiSlave_addr & 0xFE) | ((ucStart_addr/256) & 0x01);  // 4KB part has bit.1 of i2c_addr as the 256 byte page select
    //uprintf("\r\ni2c_addr: 0x%02x\r\n", i2c_addr);  // DEBUG

    addr_buf[0] = (uint8_t)(ucStart_addr & 0x00ff);
    ret = i2c0_write_then_write(i2c_addr, addr_buf, 1, ucData, uiCount);

#elif FRAM_MB85RC1M == 1
    i2c_addr = uiSlave_addr;

    addr_buf[0] = (uint8_t)(ucStart_addr/256);
    addr_buf[1] = (uint8_t)(ucStart_addr);
    ret = i2c0_write_then_write(i2c_addr, addr_buf, 2, ucData, uiCount);
#else
    #error "Unknown FRAM"
#endif

    return (ret <= 0) ? (0) : (1);
}

/******************************************************************************
 * Read multiple bytes from slave device
 *
 * Parameters:
 *  uiSlave_addr: the slave address
 *  *ucRec_Data: a variable to save the data received
 *  uiCount    : number of byte will be received
 *  ucStart_addr: register address you want to read or a control byte (Bug fix 9/9/2022:  NanoFET has large 128KB FRAM, according to Fujitsu datasheet, large FRAM requires 2 bytes of address)
 *
 * Return: none
 *****************************************************************************/
int i2c0_fram_read(unsigned char uiSlave_addr, unsigned char *ucRec_Data, uint16_t uiCount, uint16_t ucStart_addr)   //void I2C_Read(uint32_t ui32Base, unsigned char uiSlave_add, unsigned char *ucRec_Data, uint16_t uiCount, unsigned char ucStart_add, bool bDummyRead)
{
    int ret;
    unsigned char i2c_addr;
    uint8_t addr_buf[2];

#if FRAM_FM24CL04B == 1
    i2c_addr = (uiSlave_addr & 0xFE) | ((ucStart_addr/256) & 0x01);  // 4Kb 512byte part has bit.1 of i2c_addr as the 256 byte page select
    //uprintf("\r\ni2c_addr: 0x%02x\r\n", i2c_addr);   // DEBUG

    addr_buf[0] = (uint8_t)(ucStart_addr & 0x00ff);
    ret = i2c0_write_then_read(i2c_addr, addr_buf, 1, ucRec_Data, uiCount);
#elif FRAM_MB85RC1M == 1
    i2c_addr = uiSlave_addr;

    addr_buf[0] = (uint8_t)(ucStart_addr/256);
    addr_buf[1] = (uint8_t)(ucStart_addr);
    ret = i2c0_write_then_read(i2c_addr, addr_buf, 2, ucRec_Data, uiCount);
#else
    #error "Unknown FRAM"
#endif

    return (ret <= 0) ? (0) : (1);
}



int fram_probe(uint32_t* out_id)
{
    uint32_t temp = 0;
    int ret       = 0;

    // assumes i2c0_init was called
    // apparently the 24cl04b does not have a device id or a manufacturer id
    // allocate the first 4 bytes to be the id, demonstrate write/read as a means for indicating FRAM is there and useful
    framBuf[0] = 0x55;
    framBuf[1] = 0xAA;
    framBuf[2] = 0x55;
    framBuf[3] = 0xAA;
    ret = i2c0_fram_write(I2C_FRAM_ADDR, framBuf, 4, FRAM_PROBESIG_ADDR);      // probe signature is first four bytes (starting address is 0)
    if(ret <= 0)
    {
        return 0;
    }

    framBuf[0] = 0x00;
    framBuf[1] = 0x00;
    framBuf[2] = 0x00;
    framBuf[3] = 0x00;
    ret = i2c0_fram_read(I2C_FRAM_ADDR, framBuf, 4, FRAM_PROBESIG_ADDR);
    if(ret <= 0)
    {
        return 0;
    }

    temp = (((uint32_t)framBuf[3]) << 24) | (((uint32_t)framBuf[2]) << 16) | (((uint32_t)framBuf[1]) << 8) | (((uint32_t)framBuf[0]) << 0);
    if(out_id)
    {
        *out_id = temp;
    }

    if(temp != 0xAA55AA55)
    {
        return 0;
    }

    return 1;
}


int fram_apf_store_all(void)
{
    int ret1;
    int ret2;
    //this is a bit of a hack, the 'stores' should all be appropriately called in the right spot, right now plugging a hole in variable retention after sleep
    ret1 = fram_apf_vars_store();
    ret2 = fram_last_samp_store();

    return (ret1 == 1) && (ret2 == 1);
}


void fram_size_check(void)
{
    uprintf("FRAM_PROBESIG_BLKSIZE = %5u", FRAM_PROBESIG_BLKSIZE); prn_nl();

    uprintf("FRAM_SYSSAMP_BLKSIZE  = %5u, sys_samp size = %u", FRAM_SYSSAMP_BLKSIZE, sizeof(sys_samp)); prn_nl();

    uprintf("FRAM_LASTSAMP_BLKSIZE = %5u, sampl size    = %u", FRAM_LASTSAMP_BLKSIZE, sizeof(sampl)); prn_nl();

    uprintf("FRAM_APFVAR_BLKSIZE   = %5u, apf size      = %u", FRAM_APFVAR_BLKSIZE, sizeof(apf)); prn_nl();

    uprintf("FRAM_APFARRAY_BLKSIZE = %5u, apfArray size = %u", FRAM_APFARRAY_BLKSIZE, sizeof(apfArray)); prn_nl();

    uprintf("FRAM_APFDBUF_BLKSIZE  = %5u", FRAM_APFDBUF_BLKSIZE); prn_nl();
#ifdef NOCODE
    I2C_FRAM_ADDR, (unsigned char *)&apfArray, sizeof(apfArray), FRAM_APFARRAY_ADDR);
    //******************  FRAM Memory Layout:  ***********************************
    #define FRAM_PROBESIG_ADDR      0           // fram probe signature, first 4 bytes are for fram_probe signature, then 12 spare
    #define FRAM_PROBESIG_BLKSIZE   16

    #define FRAM_SPARE1_ADDR        (FRAM_PROBESIG_ADDR + FRAM_PROBESIG_BLKSIZE)   //16
    #define FRAM_SPARE1_BLKSIZE     48

    #define FRAM_SYSSAMP_ADDR       (FRAM_SPARE1_ADDR + FRAM_SPARE1_BLKSIZE)  //64          // sys_samp struct 15 * 4 = 60, pad to 128 (was 64)
    #define FRAM_SYSSAMP_BLKSIZE    128

    #define FRAM_LASTSAMP_ADDR      (FRAM_SYSSAMP_ADDR + FRAM_SYSSAMP_BLKSIZE)  //128         // sampl struct size is ~96 pad to 128
    #define FRAM_LASTSAMP_BLKSIZE   128

    #define FRAM_APFVAR_ADDR        (FRAM_LASTSAMP_ADDR + FRAM_LASTSAMP_BLKSIZE)   //256         // apf struct
    #define FRAM_APFVAR_BLKSIZE     1024

    #define FRAM_APFARRAY_ADDR      (FRAM_APFVAR_ADDR + FRAM_APFVAR_BLKSIZE)  //1024        // apfArray struct,  20K in size.   pre-initialized arrays when Zcoefs are loaded.
    #define FRAM_APFARRAY_BLKSIZE   24576       //8192*3, size of apfArray is ~ 18,856bytes

    #define FRAM_APFDBUF_ADDR       (FRAM_APFARRAY_ADDR + FRAM_APFARRAY_BLKSIZE)        // was 8192        // apf_dbuf is 2048 in size
    #define FRAM_APFDBUF_BLKSIZE    2048
#endif
}

void fram_soak_test(void)
{
    int ret;

    uint32_t indx, indx2;
    unsigned char *ucPtr;
    unsigned char chkSum, chkSum2;

    int            errNum;                   //was errno, now errNum

    // unsigned int   sendlast_byteCnt;        //APFTODO, need to init to 0
    float           DataStdDev;

    apf.DataStdDev = 7.777777;
    uprintf("fram soak test start, 10,000 times, any key to exit"); prn_nl();
    for(indx=0; indx<10000; indx++)
    {
        //apf_fram.isus_sample_ctr++;

        apf.chkSum = 0;
        chkSum = 0;
        ucPtr = (unsigned char *)&apf;
        for(indx2=0; indx2<sizeof(apf); indx2++)
        {
            chkSum += *ucPtr++;
        }
        chkSum = chkSum & 0xff;
        //chkSum += chkSum;       //to account for checksum=0
        //apf.chkSum = chkSum;

        errNum = apf_fram.errNum;
        // sendlast_byteCnt = apf_fram.sendlast_byteCnt;
        DataStdDev = apf.DataStdDev;


        // APFTODO time the store and retrieve
        ret = fram_apf_vars_store();
        if(ret <= 0)
        {
            uprintf("Err: fram_apf_vars_store failed"); prn_nl();
        }

        memset(&apf, 0, sizeof(apf));

        ret = fram_apf_vars_retrieve();
        if(ret <= 0)
        {
            uprintf("Err: fram_apf_vars_retrieve failed"); prn_nl();
        }

        ret = fram_last_samp_store();
        if(ret <= 0)
        {
            uprintf("Err: fram_last_samp_store failed"); prn_nl();
        }

        memset(&sampl, 0, sizeof(sampl));

        ret = fram_last_samp_retrieve();
        if(ret <= 0)
        {
            uprintf("Err: fram_last_samp_retrieve failed"); prn_nl();
        }

        chkSum2 = 0;
        apf.chkSum = 0;
        ucPtr = (unsigned char *)&apf;
        for(indx2=0; indx2<sizeof(apf); indx2++)
        {
            chkSum2 += *ucPtr++;
        }

        //chkSum2 &= 0xff;
        chkSum2 = chkSum2 & 0xff;

        wait_consoleTx();

        if(errNum != apf_fram.errNum)
        {
            uprintf("Err: errNum does not match"); prn_nl();
        }

        if(DataStdDev != apf.DataStdDev)
        {
            uprintf("Err: DataStdDev does not match"); prn_nl();
        }

        if(chkSum != chkSum2)
        {
            uprintf("Err: [%u] %u %02x %02x checksum does not match, apf read modify write fram_soak_test", indx, (unsigned int)sizeof(apf), chkSum, apf.chkSum); prn_nl();
        }
        else
        {
            if(indx%10 == 0)
                uprintf("[%07u]\b\b\b\b\b\b\b\b\b", indx);
        }

        if( UARTRxBytesAvail() )
        {
            uprintf("Fram Soak Test terminated by key");  prn_nl();
            UARTgetc();
            break;
        }


    }

}

void fram_test(void)
{
    int indx;

    uprintf("\r\n1st block of 128, write 127 to 0\r\n");
    for(indx=0; indx<128; indx++)               // 0->127
        framBuf[indx] = 127-indx;
    i2c0_fram_write(I2C_FRAM_ADDR, framBuf, 128, 0x00);
    for(indx=0; indx<128; indx++)
    {
        uprintf("%02x ", framBuf[indx]);
        if(indx%16 == 0x0f)
            prn_nl();
    }

    uprintf("\r\n2nd block of 128, write 0 to 127\r\n");
    for(indx=0; indx<128; indx++)
        framBuf[indx] = indx;
    i2c0_fram_write(I2C_FRAM_ADDR, framBuf, 128, 128);
    for(indx=0; indx<128; indx++)
    {
        uprintf("%02x ", framBuf[indx]);
        if(indx%16 == 0x0f)
            prn_nl();
    }

    wait_consoleTx();

    uprintf("\r\n3rd block of 128, write 255 to 128\r\n");
    for(indx=0; indx<128; indx++)
        framBuf[indx] = 255-indx;
    i2c0_fram_write(I2C_FRAM_ADDR, framBuf, 128, 256);
    for(indx=0; indx<128; indx++)
    {
        uprintf("%02x ", framBuf[indx]);
        if(indx%16 == 0x0f)
            prn_nl();
    }

    uprintf("\r\n4th block of 128, write 128 to 255\r\n");
    for(indx=0; indx<128; indx++)
        framBuf[indx] = 128+indx;
    i2c0_fram_write(I2C_FRAM_ADDR, framBuf, 128, 384);
    for(indx=0; indx<128; indx++)
    {
        uprintf("%02x ", framBuf[indx]);
        if(indx%16 == 0x0f)
            prn_nl();
    }

    wait_consoleTx();

    for(indx=0; indx<128; indx++)
        framBuf[indx] = 0x55;


    uprintf("\r\n1st block of 128, read:\r\n");
    i2c0_fram_read(I2C_FRAM_ADDR, framBuf, 128, 0);
    for(indx=0; indx<128; indx++)
    {
        uprintf("%02x ", framBuf[indx]);
        if(indx%16 == 0x0f)
            prn_nl();
    }

    uprintf("\r\n2nd block of 128, read:\r\n");
    i2c0_fram_read(I2C_FRAM_ADDR, framBuf, 128, 128);
    for(indx=0; indx<128; indx++)
    {
        uprintf("%02x ", framBuf[indx]);
        if(indx%16 == 0x0f)
            prn_nl();
    }

    wait_consoleTx();

    uprintf("\r\n3rd block of 128, read:\r\n");
    //i2c0_fram_read(I2C_FRAM_ADDR|0x01, framBuf, 128, 256, FALSE);
    i2c0_fram_read(I2C_FRAM_ADDR, framBuf, 128, 256);
    for(indx=0; indx<128; indx++)
    {
        uprintf("%02x ", framBuf[indx]);
        if(indx%16 == 0x0f)
            prn_nl();
    }

    uprintf("\r\n4th block of 128, read:\r\n");
    i2c0_fram_read(I2C_FRAM_ADDR, framBuf, 128, 384);
    for(indx=0; indx<128; indx++)
    {
        uprintf("%02x ", framBuf[indx]);
        if(indx%16 == 0x0f)
            prn_nl();
    }

    wait_consoleTx();

}


uint8_t fram_getDeviceID(void)
{

    //uint8_t localbuffer[3] = { 0, 0, 0 };
    uint8_t result = 0;
#ifdef NOCODE
    /* Get device IDs sequence  */
    /* 1/ Send 0xF8 to the I2C bus as a write instruction. bit 0: 0 => 0xF8 >> 1 */
    /* Send 0xF8 to 12C bus. Bit shift to right as beginTransmission() requires a 7bit. beginTransmission() 0 for write => 0xF8 */
    /* Send device address as 8 bits. Bit shift to left as we are using a simple write()                                        */
    /* Send 0xF9 to I2C bus. By requesting 3 bytes to read, requestFrom() add a 1 bit at the end of a 7 bits address => 0xF9    */
    /* See p.10 of http://www.fujitsu.com/downloads/MICRO/fsa/pdf/products/memory/fram/MB85RC-DS501-00017-3v0-E.pdf             */


    Wire.beginTransmission(MASTER_CODE >> 1);
    Wire.write((byte)(i2c_addr << 1));
    result = Wire.endTransmission(false);

    Wire.requestFrom(MASTER_CODE >> 1, 3);
    localbuffer[0] = (uint8_t) Wire.read();
    localbuffer[1] = (uint8_t) Wire.read();
    localbuffer[2] = (uint8_t) Wire.read();

    I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS_EXT, false);  // false means write




    /* Shift values to separate IDs */
    manufacturer = (localbuffer[0] << 4) + (localbuffer[1] >> 4);
    densitycode = (uint16_t)(localbuffer[1] & 0x0F);
    productid = ((localbuffer[1] & 0x0F) << 8) + localbuffer[2];

    if (manufacturer == FUJITSU_MANUFACT_ID) {
            switch (densitycode) {
                case DENSITY_MB85RC04V:
                    density = 4;
                    maxaddress = MAXADDRESS_04;
                    break;
                case DENSITY_MB85RC64TA:
                    density = 64;
                    maxaddress = MAXADDRESS_64;
                    break;
                case DENSITY_MB85RC256V:
                    density = 256;
                    maxaddress = MAXADDRESS_256;
                    break;
                case DENSITY_MB85RC512T:
                    density = 512;
                    maxaddress = MAXADDRESS_512;
                    break;
                case DENSITY_MB85RC1MT:
                    density = 1024;
                    maxaddress = MAXADDRESS_1024;
                    break;
                default:
                    density = 0; /* means error */
                    maxaddress = 0; /* means error */
                    if (result == 0) result = ERROR_7; /*device unidentified, comminication ok*/
                    break;
            }
    }
    else if (manufacturer == CYPRESS_MANUFACT_ID) {
            switch (densitycode) {
                case DENSITY_CY15B128J:
                    density = 128;
                    maxaddress = MAXADDRESS_128;
                    break;
                case DENSITY_CY15B256J:
                    density = 256;
                    maxaddress = MAXADDRESS_256;
                    break;
                case DENSITY_FM24V05:
                    density = 512;
                    maxaddress = MAXADDRESS_512;
                    break;
                case DENSITY_FM24V10:
                    density = 1024;
                    maxaddress = MAXADDRESS_1024;
                    break;
                default:
                    density = 0; /* means error */
                    maxaddress = 0; /* means error */
                    if (result == 0) result = ERROR_7; /*device unidentified, comminication ok*/
                    break;
            }
    }
    else {
                    density = 0; /* means error */
                    maxaddress = 0; /* means error */
                    if (result == 0) result = ERROR_7; /*device unidentified, comminication ok*/

    }
#endif
  return result;
}

