/*!
 * \file w25q64jv.c
 *
 * \brief W25Q64JW Mb Flash Memory (I2C) functions
 *
 * \copyright  J Factor Embedded Technologies LLC. 2020
 * \copyright  TJM Embedded Software LLC. 2020
 * \author  T. J. Mulrooney
 *
 * \sa
 *  <a href="https://www.adestotech.com/wp-content/uploads/DS-45DB641E-027.pdf">W25Q64JW Datasheet</a>
 *
 */
/*
 * All Rights Reserved
 * UNPUBLISHED, LICENSED SOFTWARE.
 *
 * CONFIDENTIAL AND PROPRIETARY INFORMATION
 * WHICH IS THE PROPERTY OF J-Factor Embedded Technologies.
 *
 */

#include <stdio.h>
#include "jfet_files/w25q64jv_Driver.h"

/*!
 * \fn void readNVFlashxID(uint8_t *flashId)
 *
 * \brief reads the NV Flash ID over the SPI bus.
 *
 * \param flashId pointer to the buffer to receive the Flash ID bytes
 *
 * \return none
 */
void readNVFlashxID(uint8_t *flashId)
{
    uint8_t i = 0;
    int ret;

    /* zero buffer and load the command */
    for (i = 0; i < 4; i++)
        buffer_tx[i] = 0;
    buffer_tx[0] = 0x9F;
    tx_bufs[0].len = 4;
    rx_bufs[0].len = 4;

    /* enable CS and send command  */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    /* shift bytes back to caller byte 0 is not valid data */
    for (i = 0; i < 3; i++)
        flashId[i] = buffer_rx[i + 1];
}

/*!
 * \fn void readNVFlashxStatus(uint8_t *flashStatus)
 *
 * \brief reads the 3 NV Flash status registers over the SPI bus.
 *
 * \param flashStatus pointer to the buffer to receive the Flash Status bytes
 *
 * \return none
 */
void readNVFlashxStatus(uint8_t *flashStatus)
{
    uint8_t i;
    uint8_t status[3];
    int ret;

    for (i = 0; i < 3; i++)
        status[i] = 0;

    /* zero buffer and load the command */
    for (i = 0; i < 2; i++)
        buffer_tx[i] = 0;

    /*  get status register 1 */
    buffer_tx[0] = 0x05;
    tx_bufs[0].len = 2;
    rx_bufs[0].len = 2;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    /* get requested status register */
    status[0] = buffer_rx[1];

    /* zero buffer and load the command */
    for (i = 0; i < 2; i++)
        buffer_tx[i] = 0;

    /*  get status register 2 */
    buffer_tx[0] = 0x35;
    tx_bufs[0].len = 2;
    rx_bufs[0].len = 2;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    /* get requested status register */
    status[1] = buffer_rx[1];

    /* zero buffer and load the command */
    for (i = 0; i < 2; i++)
        buffer_tx[i] = 0;

    /*  get status register 2 */
    buffer_tx[0] = 0x15;
    tx_bufs[0].len = 2;
    rx_bufs[0].len = 2;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    /* get requested status register */
    status[2] = buffer_rx[1];

    /* send back status registers */
    for (i = 0; i < 3; i++)
        flashStatus[i] = status[i];
}

#if 1
/*!
 * \fn void writeNVFlashxStatus(void)
 *
 * \brief writes NV Flash status register2 over the SPI bus.
 *
 * clears teh QSPI bit
 * \return none
 */
void writeNVFlashxStatus(void)
{
    uint8_t i;
    int ret;
    uint8_t flashStatus[3];

    /* zero buffer and load the command */
    for (i = 0; i < 2; i++)
        buffer_tx[i] = 0;

    buffer_tx[0] = 0x06; /* non-volatile write enable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    /*  set status register 1 */
    //    buffer_tx[0] = 0x01;
    //    buffer_tx[1] = 0x00;    /* SRP = 1 */
    //    tx_bufs[0].len = 2;
    //    rx_bufs[0].len = 2;

    /* enable CS and send command */
    //    ret = spi_transceive(spi, &spi_cfg, &tx, &rx);

    /*  set status register 2 */
    buffer_tx[0] = 0x31;
    buffer_tx[1] = 0x00; /* QE = 0 */
    tx_bufs[0].len = 2;
    rx_bufs[0].len = 2;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    readNVFlashxStatus(flashStatus);

    buffer_tx[0] = 0x04; /* write disable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);
}
#endif

/*!
 * \fn void flashxErasePage(uint32_t address)
 *
 * \brief erases a 256 byte page over the SPI bus.
 *
 * \param address address of the page to be erased
 *
 * \return none
 */
void flashxErasePage(uint32_t address)
{
    uint8_t flashStatusIn[3];
    uint32_t address32 = address << 11;
    int ret;

    buffer_tx[0] = 0x06; /* write enable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    buffer_tx[0] = 0x20; /* block 1 erase */
    buffer_tx[1] = (address32 >> 16) & 0xFF;
    buffer_tx[2] = (address32 >> 8) & 0xFF;
    buffer_tx[3] = (address32 >> 0) & 0xFF;
    tx_bufs[0].len = 4;
    rx_bufs[0].len = 4;

    /* enable CS and send command to read ID into buffer */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    printk("Erasing sector (16 pages) %d. Please wait ...\r\n", address);

    while (1) /* wait until flag goes away */
    {
        readNVFlashxStatus(flashStatusIn);
        //        printk("Flash Status: 0x%02X 0x%02X\r\n",flashStatusIn[0],flashStatusIn[1]);
        if ((flashStatusIn[0] & 0x01) == 0x00)
        {
            break;
        }
        k_sleep(K_MSEC(1));
    }

    buffer_tx[0] = 0x04; /* write disable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);
}

/*!
 * \fn void flashxEraseBlock1(uint32_t address)
 *
 * \brief erases a 2K block page over the SPI bus.
 *
 * \param address address of the block to be erased
 *
 * \return none
 */
void flashxEraseBlock1(uint32_t address)
{
    uint8_t flashStatusIn[3];
    uint32_t address32 = address << 7;
    int ret;

    buffer_tx[0] = 0x06; /* write enable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    buffer_tx[0] = 0x52; /* block 1 erase */
    buffer_tx[1] = (address32 >> 16) & 0xFF;
    buffer_tx[2] = (address32 >> 8) & 0xFF;
    buffer_tx[3] = (address32 >> 0) & 0xFF;
    tx_bufs[0].len = 4;
    rx_bufs[0].len = 4;

    /* enable CS and send command to read ID into buffer */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    printk("Erasing Block %d. Please wait ...\r\n", address);

    while (1) /* wait until flag goes away */
    {
        readNVFlashxStatus(flashStatusIn);
        //        printk("Flash Status: 0x%02X 0x%02X\r\n",flashStatusIn[0],flashStatusIn[1]);
        if ((flashStatusIn[0] & 0x01) == 0x00)
        {
            break;
        }
        k_sleep(K_MSEC(1));
    }

    buffer_tx[0] = 0x04; /* write disable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);
}

/*!
 * \fn void flashxEraseBlock1(uint32_t address)
 *
 * \brief erases a 2K block page over the SPI bus.
 *
 * \param address address of the block to be erased
 *
 * \return none
 */
void flashxEraseBlock2(uint32_t address)
{
    uint8_t flashStatusIn[3];
    uint32_t address32 = address << 4;
    int ret;

    buffer_tx[0] = 0x06; /* write enable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    buffer_tx[0] = 0xD8; /* block 1 erase */
    buffer_tx[1] = (address32 >> 16) & 0xFF;
    buffer_tx[2] = (address32 >> 8) & 0xFF;
    buffer_tx[3] = (address32 >> 0) & 0xFF;
    tx_bufs[0].len = 4;
    rx_bufs[0].len = 4;

    /* enable CS and send command to read ID into buffer */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    printk("Erasing Block %d. Please wait ...\r\n", address);

    while (1) /* wait until flag goes away */
    {
        readNVFlashxStatus(flashStatusIn);
        //        printk("Flash Status: 0x%02X 0x%02X\r\n",flashStatusIn[0],flashStatusIn[1]);
        if ((flashStatusIn[0] & 0x01) == 0x00)
        {
            break;
        }
        k_sleep(K_MSEC(1));
    }

    buffer_tx[0] = 0x04; /* write disable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);
}

/*!
 * \fn void flashxEraseSector(uint32_t address)
 *
 * \brief erases a 256K byte sector over the SPI bus.
 *
 * \param address address of the sector to be erased
 *
 * \return none
 */
void flashxEraseSector(uint32_t address)
{
    uint8_t flashStatusIn[3];
    uint32_t address32 = address << 12;
    int ret;

    buffer_tx[0] = 0x06; /* write enable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    buffer_tx[0] = 0x20; /* 4K sector erase */
    buffer_tx[1] = (address32 >> 16) & 0xFF;
    buffer_tx[2] = (address32 >> 8) & 0xFF;
    buffer_tx[3] = (address32 >> 0) & 0xFF;
    tx_bufs[0].len = 4;
    rx_bufs[0].len = 4;

    /* enable CS and send command to read ID into buffer */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    printk("Erasing Sector %d. Please wait ...\r\n", address);

    while (1) /* wait until flag goes away */
    {
        readNVFlashxStatus(flashStatusIn);
        //        printk("Flash Status: 0x%02X 0x%02X\r\n",flashStatusIn[0],flashStatusIn[1]);
        if ((flashStatusIn[0] & 0x01) == 0x00)
        {
            break;
        }
        k_sleep(K_MSEC(1));
    }

    buffer_tx[0] = 0x04; /* write disable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);
}

/*!
 * \fn void flashxErase(void)
 *
 * \brief erases the entire 8 Mb over the SPI bus.
 *
 * \return none
 */
void flashxErase(void)
{
    uint8_t flashStatusIn[3];
    int ret;

    buffer_tx[0] = 0x06; /* write enable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    buffer_tx[0] = 0xC7; /* write enable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command to read ID into buffer */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    printk("Erasing entire device. Please wait ...\r\n");

    while (1) /* wait until flag goes away */
    {
        readNVFlashxStatus(flashStatusIn);
        //       printk("Flash Status: 0x%02X 0x%02X %d\r\n",flashStatusIn[0],flashStatusIn[1],(flashStatusIn[0] & 0x80));
        if ((flashStatusIn[0] & 0x01) == 0x00)
        {
            break;
        }
        k_sleep(K_MSEC(1));
    }
    printk("Entire device erased\r\n");

    buffer_tx[0] = 0x04; /* write disable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);
}

/*!
 * \fn void flashxReadPage(uint32_t address,  uint8_t *flashRead)
 *
 * \brief reads a 256 byte page over the SPI bus.
 *
 * \param address 24 bit memory address of page to read
 * \param flashRead - address of data array to received bytes from NV memory
 *
 * \return none
 */
void flashxReadPage(uint32_t address, uint8_t *flashRead)
{
    uint16_t i;
    uint32_t address32;
    int ret;
    uint8_t readBuffer[256];

    /* start first 64 byte read from page */
    /* zero buffer and load the command */
    address32 = (address << 8) + 0; /* set first address */
    for (i = 0; i < 64 + 4; i++)
        buffer_tx[i] = 0;
    buffer_tx[0] = 0x03;
    buffer_tx[1] = (address32 >> 16) & 0xFF;
    buffer_tx[2] = (address32 >> 8) & 0xFF;
    buffer_tx[3] = (address32 >> 0) & 0xFF;
    tx_bufs[0].len = 64 + 4;
    rx_bufs[0].len = 64 + 4;

    //    printk("Flash Page Read: 0x%08X\r\n",address);
    //    printk("%02X %02X %02X %02X\r\n",flashReadCmd[0],flashReadCmd[1],flashReadCmd[2],flashReadCmd[3]);

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    /* put bytes in buffer ignore first 4 bytes */
    for (i = 0; i < 64; i++)
        readBuffer[i] = buffer_rx[i + 4];
    /* end first 64 byte read from page */

    /* start second 64 byte read from page */
    /* zero buffer and load the command */
    address32 = (address << 8) + 64; /* set first address */
    for (i = 0; i < 64 + 4; i++)
        buffer_tx[i] = 0;
    buffer_tx[0] = 0x03;
    buffer_tx[1] = (address32 >> 16) & 0xFF;
    buffer_tx[2] = (address32 >> 8) & 0xFF;
    buffer_tx[3] = (address32 >> 0) & 0xFF;
    tx_bufs[0].len = 64 + 4;
    rx_bufs[0].len = 64 + 4;

    //    printk("Flash Page Read: 0x%08X\r\n",address);
    //    printk("%02X %02X %02X %02X\r\n",flashReadCmd[0],flashReadCmd[1],fsheadCmd[2],flashReadCmd[3]);

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    /* put bytes in buffer ignore first 4 bytes */
    for (i = 0; i < 64; i++)
        readBuffer[i + 64] = buffer_rx[i + 4];
    /* end second 64 byte read from page */

    /* start third 64 byte read from page */
    /* zero buffer and load the command */
    address32 = (address << 8) + 128; /* set first address */
    for (i = 0; i < 64 + 4; i++)
        buffer_tx[i] = 0;
    buffer_tx[0] = 0x03;
    buffer_tx[1] = (address32 >> 16) & 0xFF;
    buffer_tx[2] = (address32 >> 8) & 0xFF;
    buffer_tx[3] = (address32 >> 0) & 0xFF;
    tx_bufs[0].len = 64 + 4;
    rx_bufs[0].len = 64 + 4;

    //    printk("Flash Page Read: 0x%08X\r\n",address);
    //    printk("%02X %02X %02X %02X\r\n",flashReadCmd[0],flashReadCmd[1],flashReadCmd[2],flashReadCmd[3]);

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    /* put bytes in buffer ignore first 4 bytes */
    for (i = 0; i < 64; i++)
        readBuffer[i + 128] = buffer_rx[i + 4];
    /* end third 64 byte read from page */

    /* start fourth 64 byte read from page */
    /* zero buffer and load the command */
    address32 = (address << 8) + 192; /* set first address */
    for (i = 0; i < 64 + 4; i++)
        buffer_tx[i] = 0;
    buffer_tx[0] = 0x03;
    buffer_tx[1] = (address32 >> 16) & 0xFF;
    buffer_tx[2] = (address32 >> 8) & 0xFF;
    buffer_tx[3] = (address32 >> 0) & 0xFF;
    tx_bufs[0].len = 64 + 4;
    rx_bufs[0].len = 64 + 4;

    //    printk("Flash Page Read: 0x%08X\r\n",address);
    //    printk("%02X %02X %02X %02X\r\n",flashReadCmd[0],flashReadCmd[1],flashReadCmd[2],flashReadCmd[3]);

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    /* put bytes in buffer ignore first 4 bytes */
    for (i = 0; i < 64; i++)
        readBuffer[i + 192] = buffer_rx[i + 4];
    /* end fourth 64 byte read from page */

    /* shift bytes back to caller byte 0 is not valid data */
    for (i = 0; i < 256; i++)
    {
        flashRead[i] = readBuffer[i];
    }
}

/*
 * \fn void flashxWritePage(uint32_t page, uint32_t address, uint8_t *data, uint16_t count)
 *
 * \brief writes data to address in serial flash over the SPI bus.
 *
 * \param page 24 bit memory address of page to write
 * \param address address within page to begin writing
 * \param data address of data array to get bytes to store bytes in NV memory
 * \param count number of bytes to write
 *
 * \return none
 */
void flashxWritePage(uint32_t page, uint32_t address, uint8_t *data, uint16_t count)
{
    int i;
    uint8_t flashStatusIn[2];
    //    uint8_t flashIn[256+4];
    uint32_t address32 = page << 8;
    uint8_t dataPage[256 + 4];
    int ret;

#if 0
    printk("flashxWritePage page: %d length: %d\r\n",page,count);
    for(i=0;i<count;i++)
    {
      if( (i & 0xf) == 0)
        printk("\r\n %02X",i);
      printk(" 0x%02X",data[i]);
    }
#endif
    buffer_tx[0] = 0x06; /* write enable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    //    printk("page: %d address: %d data: %02X count: %d\r\n",page,address,data[0],count);
    flashxReadPage(page, dataPage); /* read in page data */

    //    for(i=0;i<256;i++)
    //   	printk("i: %d data: %02X\r\n",i,dataPage[i]);
    for (i = 0; i < count; i++) /* move in new data */
        dataPage[i + address] = data[i];
    //    for(i=0;i<256;i++)
    //    	printk("i: %d data: %02X\r\n",i,dataPage[i]);

    /* write first 64 byte write */
    address32 = (page << 8) + 0;
    buffer_tx[0] = 0x02; /* chip program */
    buffer_tx[1] = (address32 >> 16) & 0xFF;
    buffer_tx[2] = (address32 >> 8) & 0xFF;
    buffer_tx[3] = (address32 >> 0) & 0xFF;
    for (i = 0; i < 64; i++)
        buffer_tx[i + 4] = dataPage[i];
    tx_bufs[0].len = 64 + 4;
    rx_bufs[0].len = 64 + 4;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    while (1) /* wait until flag goes away */
    {
        readNVFlashxStatus(flashStatusIn);
        //        PRINTF("Flash Status: 0x%02X 0x%02X\r\n",flashStatusIn[0],flashStatusIn[1]);
        if ((flashStatusIn[0] & 0x01) == 0x00)
        {
            break;
        }
        k_sleep(K_MSEC(1));
    }
    /* end of first 64 byte write */

    /* write second 64 byte write */
    address32 = (page << 8) + 64;
    buffer_tx[0] = 0x02; /* chip program */
    buffer_tx[1] = (address32 >> 16) & 0xFF;
    buffer_tx[2] = (address32 >> 8) & 0xFF;
    buffer_tx[3] = (address32 >> 0) & 0xFF;
    for (i = 0; i < 64; i++)
        buffer_tx[i + 4] = dataPage[i + 64];
    tx_bufs[0].len = 64 + 4;
    rx_bufs[0].len = 64 + 4;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    while (1) /* wait until flag goes away */
    {
        readNVFlashxStatus(flashStatusIn);
        //        PRINTF("Flash Status: 0x%02X 0x%02X\r\n",flashStatusIn[0],flashStatusIn[1]);
        if ((flashStatusIn[0] & 0x01) == 0x00)
        {
            break;
        }
        k_sleep(K_MSEC(1));
    }
    /* end of second 64 byte write */

    /* write third 64 byte write */
    address32 = (page << 8) + 128;
    buffer_tx[0] = 0x02; /* chip program */
    buffer_tx[1] = (address32 >> 16) & 0xFF;
    buffer_tx[2] = (address32 >> 8) & 0xFF;
    buffer_tx[3] = (address32 >> 0) & 0xFF;
    for (i = 0; i < 64; i++)
        buffer_tx[i + 4] = dataPage[i + 128];
    tx_bufs[0].len = 64 + 4;
    rx_bufs[0].len = 64 + 4;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    while (1) /* wait until flag goes away */
    {
        readNVFlashxStatus(flashStatusIn);
        //        PRINTF("Flash Status: 0x%02X 0x%02X\r\n",flashStatusIn[0],flashStatusIn[1]);
        if ((flashStatusIn[0] & 0x01) == 0x00)
        {
            break;
        }
        k_sleep(K_MSEC(1));
    }
    /* end of third 64 byte write */

    /* write fourth 64 byte write */
    address32 = (page << 8) + 192;
    buffer_tx[0] = 0x02; /* chip program */
    buffer_tx[1] = (address32 >> 16) & 0xFF;
    buffer_tx[2] = (address32 >> 8) & 0xFF;
    buffer_tx[3] = (address32 >> 0) & 0xFF;
    for (i = 0; i < 64; i++)
        buffer_tx[i + 4] = dataPage[i + 192];
    tx_bufs[0].len = 64 + 4;
    rx_bufs[0].len = 64 + 4;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    while (1) /* wait until flag goes away */
    {
        readNVFlashxStatus(flashStatusIn);
        //        PRINTF("Flash Status: 0x%02X 0x%02X\r\n",flashStatusIn[0],flashStatusIn[1]);
        if ((flashStatusIn[0] & 0x01) == 0x00)
        {
            break;
        }
        k_sleep(K_MSEC(1));
    }
    /* end of fourth 64 byte write */

    buffer_tx[0] = 0x04; /* write disable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);
}

/*!
 * \fn void flashxFillPage(uint32_t address, uint16_t data)
 *
 * \brief fills a 256 byte page with data over the SPI bus.
 *
 * \param address 24 bit memory address of page to write
 * \param data byte to fill in page in NV memory
 *
 * \return none
 */
void flashxFillPage(uint32_t address, uint16_t data)
{
    int i;
    uint8_t flashStatusIn[2];
    uint32_t address32 = address << 8;
    int ret;

    buffer_tx[0] = 0x06; /* write enable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    /* fill first 64 bytes */
    address32 = (address << 8) + 0;
    buffer_tx[0] = 0x02; /* chip program */
    buffer_tx[1] = (address32 >> 16) & 0xFF;
    buffer_tx[2] = (address32 >> 8) & 0xFF;
    buffer_tx[3] = (address32 >> 0) & 0xFF;
    for (i = 0; i < 64; i++)
        buffer_tx[i + 4] = data;
    tx_bufs[0].len = 64 + 4;
    rx_bufs[0].len = 64 + 4;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    while (1) /* wait until flag goes away */
    {
        readNVFlashxStatus(flashStatusIn);
        //       printk("Flash Status: 0x%02X 0x%02X\r\n",flashStatusIn[0],flashStatusIn[1]);
        if ((flashStatusIn[0] & 0x01) == 0x00)
        {
            break;
        }
        //            delay_ms(1);
    }
    /* end fill first 64 bytes */

    /* fill second 64 bytes */
    address32 = (address << 8) + 64;
    buffer_tx[0] = 0x02; /* chip program */
    buffer_tx[1] = (address32 >> 16) & 0xFF;
    buffer_tx[2] = (address32 >> 8) & 0xFF;
    buffer_tx[3] = (address32 >> 0) & 0xFF;
    for (i = 0; i < 64; i++)
        buffer_tx[i + 4] = data;
    tx_bufs[0].len = 64 + 4;
    rx_bufs[0].len = 64 + 4;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    while (1) /* wait until flag goes away */
    {
        readNVFlashxStatus(flashStatusIn);
        //       printk("Flash Status: 0x%02X 0x%02X\r\n",flashStatusIn[0],flashStatusIn[1]);
        if ((flashStatusIn[0] & 0x01) == 0x00)
        {
            break;
        }
        //            delay_ms(1);
    }
    /* end fill second 64 bytes */

    /* fill third 64 bytes */
    address32 = (address << 8) + 128;
    buffer_tx[0] = 0x02; /* chip program */
    buffer_tx[1] = (address32 >> 16) & 0xFF;
    buffer_tx[2] = (address32 >> 8) & 0xFF;
    buffer_tx[3] = (address32 >> 0) & 0xFF;
    for (i = 0; i < 64; i++)
        buffer_tx[i + 4] = data;
    tx_bufs[0].len = 64 + 4;
    rx_bufs[0].len = 64 + 4;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    while (1) /* wait until flag goes away */
    {
        readNVFlashxStatus(flashStatusIn);
        //       printk("Flash Status: 0x%02X 0x%02X\r\n",flashStatusIn[0],flashStatusIn[1]);
        if ((flashStatusIn[0] & 0x01) == 0x00)
        {
            break;
        }
        //            delay_ms(1);
    }
    /* end fill third 64 bytes */

    /* fill fourth 64 bytes */
    address32 = (address << 8) + 192;
    buffer_tx[0] = 0x02; /* chip program */
    buffer_tx[1] = (address32 >> 16) & 0xFF;
    buffer_tx[2] = (address32 >> 8) & 0xFF;
    buffer_tx[3] = (address32 >> 0) & 0xFF;
    for (i = 0; i < 64; i++)
        buffer_tx[i + 4] = data;
    tx_bufs[0].len = 64 + 4;
    rx_bufs[0].len = 64 + 4;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);

    while (1) /* wait until flag goes away */
    {
        readNVFlashxStatus(flashStatusIn);
        //       printk("Flash Status: 0x%02X 0x%02X\r\n",flashStatusIn[0],flashStatusIn[1]);
        if ((flashStatusIn[0] & 0x01) == 0x00)
        {
            break;
        }
        //            delay_ms(1);
    }
    /* end fill fourth 64 bytes */

    buffer_tx[0] = 0x04; /* write disable */
    tx_bufs[0].len = 1;
    rx_bufs[0].len = 1;

    /* enable CS and send command */
    ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);
}

/*!
 * \fn void flashClearParameters(void)
 *
 * \brief clears/initializes the flash parameters in RAM
 *
 *  This is called on power up reset after the NV flash parameters have been erased \n
 * from Page 0 1nd 1. only called if the Key is not set in the NV Flash Parameters.
 *
 * \return none
 */
void flashxClearParameters(void)
{

    //    flashParameters.tempUnitsCentigrade = true;
    //    flashParameters.dateSet = false;
    //    flashParameters.timeZone = DEFAULT_TIMEZONE;
    //	flashParameters.alarmsEnabled = false;
    //	flashParameters.gpio09Mode = 1;
    //    flashParameters.lowPower = 0;
    //    flashParameters.gpsEnable = false;
    //    flashParameters.gpsExternal = false;
    //    jfet_dk_set_led(GPSENB,flashParameters.gpsEnable?1:0);
    //    flashParameters.modenPMEnable = false;
    //    jfet_dk_set_led(GPSENB,flashParameters.modenPMEnable?1:0);
    //    flashParameters.offsetAM2315 = 0;
    //    flashParameters.offsetAM2315Humidity = 0;
    //    flashParameters.offsetMSPPressure = 0;
    //    flashParameters.offsetRTD = 0;
    //    flashParameters.offsetThermistor = 0;
    //    flashParameters.sw1 = false;
    //    flashParameters.sw2 = false;
    //	flashParameters.silent = false;
    //    flashParameters.dutyCycle = DEFAULT_DUTYCYCLE;
    //    strcpy(flashParameters.sensorID,"No ID");
    //    strcpy(flashParameters.sensorName,"No Sensor Name");
    //    strcpy(flashParameters.customer,"No Customer Name");
    //    strcpy(flashParameters.location,"No Location Name");
    //    strcpy(flashParameters.group,"No Group Name");
    //    strcpy(flashParameters.distributor,"No Distributor Name");
    //    strcpy(flashParameters.clientID,"x");
    ////    strcpy(flashParameters.edrx_param,CONFIG_LTE_EDRX_REQ_VALUE);
    ////    strcpy(flashParameters.ptw_param,CONFIG_LTE_PTW_VALUE);
    //    strcpy(flashParameters.ptw_param,"");
    //    strcpy(flashParameters.psm_param_rat,CONFIG_LTE_PSM_REQ_RAT);
    //    strcpy(flashParameters.psm_param_rptau,CONFIG_LTE_PSM_REQ_RPTAU);
    //    memset(&flashParameters.tempAlarms[0],0,sizeof(tempAlarmStruct) * MAX_NUMBER_TEMPERATURE_SENSORS);
    //    flashParameters.tempAlarmValid = DEFAULT_TEMPALARMVALID;
    //    flashParameters.tempAlarmCheck = DEFAULT_TEMPALARMCHECK;
    //    memset(&flashParameters.humidityAlarms[0],0,sizeof(humidityAlarmStruct) * MAX_NUMBER_HUMIDITY_SENSORS);
    //    flashParameters.humidityAlarmValid = DEFAULT_HUMIDITYALARMVALID;
    //    flashParameters.humidityAlarmCheck = DEFAULT_HUMIDITYALARMCHECK;
    //    memset(&flashParameters.pressureAlarms[0],0,sizeof(pressureAlarmStruct) * MAX_NUMBER_PRESSURE_SENSORS);
    //    flashParameters.pressureAlarmValid = DEFAULT_PRESSUREALARMVALID;
    //    flashParameters.pressureAlarmCheck = DEFAULT_PRESSUREALARMCHECK;
    //    memset(&flashParameters.ezoecAlarms[0],0,sizeof(ezoecAlarmStruct) * MAX_NUMBER_EZOEC_SENSORS);
    //    flashParameters.ezoecAlarmValid = DEFAULT_EZOECALARMVALID;
    //    flashParameters.ezoecAlarmCheck = DEFAULT_EZOECALARMCHECK;
    //    memset(&flashParameters.powerAlarms[0],0,sizeof(powerAlarmStruct) * MAX_NUMBER_POWER_SENSORS);
    //    flashParameters.powerAlarmValid = DEFAULT_POWERALARMVALID;
    //    flashParameters.powerAlarmCheck = DEFAULT_POWERALARMCHECK;
    //    flashParameters.savedCount = 0;
    //    flashParameters.nextSavedRead = 0;
    //    flashParameters.nextSavedWrite = 0;
    // #if 0
    //    flashParameters.tempAlarms[1].tempAlarm = 0xF;
    //    flashParameters.tempAlarms[1].lowTempCheck = (int16_t)(20.0 * 100);
    //    flashParameters.tempAlarms[1].lowTempAlarmValue = (int16_t)(13.67 * 100);
    //    flashParameters.tempAlarms[1].highTempCheck = (int16_t)(30.0 * 100);
    //    flashParameters.tempAlarms[1].highTempAlarmValue = (int16_t)(33.67 * 100);
    //    struct tm  time;
    //    time_t curTime;
    //    getRTCTime(&time);
    //    curTime = mktime(&time);
    //    flashParameters.tempAlarms[1].lowTempTime = curTime;
    //    flashParameters.tempAlarms[1].lowTempTime = curTime;
    //    flashParameters.tempAlarms[1].highTempTime = curTime;
    //    flashParameters.tempAlarms[1].highTempTime = curTime;
    // #endif
}

/*!
 * \fn void void displayFlashParameters(void)
 *
 * \brief displays the NV flash parameters.
 *
 * This also first loads the RAM flash parameters from the NV Flash Parameters\n
 * so it reloads the RAM flash parameters.
 *
 * \return none
 */
void displayFlashxParameters(void)
{
    printk("XXX FLASH Parameters\r\n");
#if 0
	char str[70];
    uint8_t data0[256 + 8];
    int i;
    uint8_t *pFlashParameters = (uint8_t *)&flashParameters;
    struct tm  *pTime;
    time_t curTime;

    if(flashParameters.silent)
      return;
    printk("Flash Parameters Size: %d\r\n",sizeof(flashParametersStruct));
    if(sizeof(flashParametersStruct) <= 256)
    {
        flashxReadPage(FLASHPARAMETERSTART,data0);
        for(i=0;i<sizeof(flashParametersStruct);i++)
        	pFlashParameters[i] = data0[i];
    }
    else if(sizeof(flashParametersStruct) <= 512)
    {
        flashxReadPage(FLASHPARAMETERSTART,data0);
         for(i=0;i<256;i++)
            pFlashParameters[i] = data0[i];
        flashxReadPage(FLASHPARAMETERSTART+1,data0);
        for(i=0;i<sizeof(flashParametersStruct) - 256;i++)
            pFlashParameters[i + 256] = data0[i];
    }
   else if(sizeof(flashParametersStruct) <= 768)
     {
        flashxReadPage(FLASHPARAMETERSTART,data0);
        for(i=0;i<256;i++)
            pFlashParameters[i] = data0[i];
        flashxReadPage(FLASHPARAMETERSTART+1,data0);
        for(i=0;i<256;i++)
            pFlashParameters[i + 256] = data0[i];
        flashxReadPage(FLASHPARAMETERSTART+2,data0);
        for(i=0;i<sizeof(flashParametersStruct) - 512;i++)
            pFlashParameters[i + 512] = data0[i];
    }
    else 
    {
        flashxReadPage(FLASHPARAMETERSTART,data0);
        for(i=0;i<256;i++)
            pFlashParameters[i] = data0[i];
        flashxReadPage(FLASHPARAMETERSTART+1,data0);
        for(i=0;i<256;i++)
            pFlashParameters[i + 256] = data0[i];
        flashxReadPage(FLASHPARAMETERSTART+2,data0);
        for(i=0;i<256;i++)
            pFlashParameters[i + 512] = data0[i];
        flashxReadPage(FLASHPARAMETERSTART+3,data0);
        for(i=0;i<sizeof(flashParametersStruct) - 768;i++)
            pFlashParameters[i + 768] = data0[i];
    }
    if(flashParameters.key == FLASHPARAMETERKEY)
    {
        printk("    Key: 0x%08X\r\n",(unsigned int)flashParameters.key);
//        printk("    Date Set: %s\r\n",flashParameters.dateSet?"True":"False");
        printk("    Time Zone: %d\r\n",flashParameters.timeZone);
        printk("    Duty Cycle: %d Seconds\r\n",flashParameters.dutyCycle);
        printk("    SW1: %s\r\n",flashParameters.sw1?"True":"False");
        printk("    SW2: %s\r\n",flashParameters.sw2?"True":"False");
        printk("    GPIO09 Mode: %s\r\n",flashParameters.gpio09Mode?"Input":"Output");
        if(flashParameters.lowPower > 2)
            flashParameters.lowPower = 0;
        printk("    Low Power: %s\r\n",powerModes[flashParameters.lowPower]);
        printk("    Mode_nPM Enable: %s\r\n",flashParameters.modenPMEnable?"True":"False");
//        printk("    GPS Enable: %s\r\n",flashParameters.gpsEnable?"True":"False");
//        printk("    GPS External: %s\r\n",flashParameters.gpsExternal?"External":"Internal");
//        printk("    GPS Fix Check: %ld seconds\r\n",(long int)flashParameters.gpsFixCheck);
        printk("    Offset Am2315: %3.3f C\r\n",flashParameters.offsetAM2315 / 1000.0);
        printk("    Offset Am2315 Humidity: %3.3f %%\r\n",flashParameters.offsetAM2315Humidity / 1000.0);
        printk("    Offset MSP300 Pressure: %3.3f PSI\r\n",flashParameters.offsetMSPPressure / 1000.0);
        printk("    Offset RTD: %3.3f C\r\n",flashParameters.offsetRTD / 1000.0);
        printk("    Offset Thermistor: %3.3f C\r\n",flashParameters.offsetThermistor / 1000.0);
        printk("    Silent: %s\r\n",flashParameters.silent?"True":"False");
        printk("    Sensor ID: %s\r\n",flashParameters.sensorID);
        printk("    Sensor Name: %s\r\n",flashParameters.sensorName);
        printk("    Customer: %s\r\n",flashParameters.customer);
        printk("    Location: %s\r\n",flashParameters.location);
        printk("    Group: %s\r\n",flashParameters.group);
        printk("    Distributor: %s\r\n",flashParameters.distributor);
        printk("    Client ID: %s\r\n",flashParameters.clientID);
        printk("    EDRX Parameter: %s\r\n",flashParameters.edrx_param);
//        printk("    EDRX PTW: %s\r\n",flashParameters.ptw_param);
        printk("    PSM Tau: %s\r\n",flashParameters.psm_param_rptau);
        printk("    PSM AT: %s\r\n",flashParameters.psm_param_rat);
        printk("    JSON Packets Saved: %d\r\n",flashParameters.savedCount);
        printk("    Next Saved JSON Packet Read: %d 0x%X\r\n",flashParameters.nextSavedRead,flashParameters.nextSavedRead);
        printk("    Next Saved JSON Packet Write: %d 0x%X\r\n",flashParameters.nextSavedWrite,flashParameters.nextSavedWrite);
        printk("    Global Alarms Enabled: %s\r\n\r\n",flashParameters.alarmsEnabled?"True":"False");
        printk("    Temperature Units: %s\r\n",flashParameters.tempUnitsCentigrade?"C":"F");

        printk("    Temperature Alarm Check: %d seconds\r\n",flashParameters.tempAlarmCheck);
        printk("    Temperature Alarms Valid: %d seconds\r\n",flashParameters.tempAlarmValid);
        printk("    Temperature Alarms\r\n    Sensor\tLow E\tLow A\tLow T\tLow V\tLow Time\t\t\tLow Valid\r\n");
        for(i=0; i < MAX_NUMBER_TEMPERATURE_SENSORS; i++)
        {
            printk("    %d %s\t",i,tempSensorNames[tempSensorsPresent[i]]);
            if(flashParameters.tempAlarms[i].tempAlarm & LOWTEMPENABLE)
                printk("E\t");
            else
                printk("D\t");
            if(flashParameters.tempAlarms[i].tempAlarm & LOWTEMPACTIVE)
            {
//                curTime = flashParameters.tempAlarms[i].lowTempTime + (flashParameters.timeZone * 60 * 60);
                curTime = flashParameters.tempAlarms[i].lowTempTime ;
                pTime = localtime(&curTime);
                sprintf(str,"%3.2f\t%3.2f\t%02d/%02d/%04d %02d:%02d:%02d", \
                (flashParameters.tempAlarms[i].lowTempCheck * 1.0)/ 100.0,(flashParameters.tempAlarms[i].lowTempAlarmValue * 1.0)/ 100.0, \
                pTime->tm_mon+1,pTime->tm_mday,pTime->tm_year + 1900,pTime->tm_hour,pTime->tm_min,pTime->tm_sec);
                printk("A\t%s\t%d",str,flashParameters.tempAlarms[i].lowTempAlarmValid);
            }
            else
            {
                sprintf(str,"%3.2f\t\t\t\t\t\t%d",(flashParameters.tempAlarms[i].lowTempCheck * 1.0)/ 100.0,flashParameters.tempAlarms[i].lowTempAlarmValid);
                printk("I\t%s",str);
            }
            printk("\r\n");
        }
        printk("\r\n    Sensor\tHigh E\tHigh A\tHigh T\tHigh V\tHigh Time\t\t\tHigh Valid\r\n");
        for(i=0; i < MAX_NUMBER_TEMPERATURE_SENSORS; i++)
        {
            printk("    %d %s\t",i,tempSensorNames[tempSensorsPresent[i]]);
            if(flashParameters.tempAlarms[i].tempAlarm & HIGHTEMPENABLE)
                printk("E\t");
            else
                printk("D\t");
            if(flashParameters.tempAlarms[i].tempAlarm & HIGHTEMPACTIVE)
            {
//                curTime = flashParameters.tempAlarms[i].highTempTime + (flashParameters.timeZone * 60 * 60);
                curTime = flashParameters.tempAlarms[i].highTempTime;
                pTime = localtime(&curTime);
                sprintf(str,"%3.2f\t%3.2f\t%02d/%02d/%04d %02d:%02d:%02d", \
                (flashParameters.tempAlarms[i].highTempCheck * 1.0)/ 100.0,(flashParameters.tempAlarms[i].highTempAlarmValue * 1.0)/ 100.0, \
                pTime->tm_mon+1,pTime->tm_mday,pTime->tm_year + 1900,pTime->tm_hour,pTime->tm_min,pTime->tm_sec);
                printk("A\t%s\t%d",str,flashParameters.tempAlarms[i].highTempAlarmValid);
            }
            else
            {
                sprintf(str,"%3.2f\t\t\t\t\t\t%d",(flashParameters.tempAlarms[i].highTempCheck * 1.0)/ 100.0,flashParameters.tempAlarms[i].highTempAlarmValid);
                printk("I\t%s",str);
            }
            printk("\r\n");
        }

        printk("\r\n    Humidity Alarms Check: %d seconds\r\n",flashParameters.humidityAlarmCheck);
        printk("    Humidity Alarms Valid: %d seconds\r\n",flashParameters.humidityAlarmValid);
        printk("    Humidity Alarms\r\n    Sensor\tLow E\tLow A\tLow T\tLow V\tLow Time\t\t\tLow Valid\r\n");
        for(i=0; i < MAX_NUMBER_HUMIDITY_SENSORS; i++)
        {
            printk("    %d %s\t",i,humiditySensorNames[humiditySensorsPresent[i]]);
            if(flashParameters.humidityAlarms[i].humidityAlarm & LOWHUMIDITYENABLE)
                printk("E\t");
            else
                printk("D\t");
            if(flashParameters.humidityAlarms[i].humidityAlarm & LOWHUMIDITYACTIVE)
            {
//                curTime = flashParameters.humidityAlarms[i].lowHumidityTime + (flashParameters.timeZone * 60 * 60);
                curTime = flashParameters.humidityAlarms[i].lowHumidityTime ;
                pTime = localtime(&curTime);
                sprintf(str,"%3.2f\t%3.2f\t%02d/%02d/%04d %02d:%02d:%02d", \
                (flashParameters.humidityAlarms[i].lowHumidityCheck * 1.0)/ 100.0,(flashParameters.humidityAlarms[i].lowHumidityAlarmValue * 1.0)/ 100.0, \
                pTime->tm_mon+1,pTime->tm_mday,pTime->tm_year + 1900,pTime->tm_hour,pTime->tm_min,pTime->tm_sec);
                printk("A\t%s\t%d",str,flashParameters.humidityAlarms[i].lowHumidityAlarmValid);
            }
            else
            {
                sprintf(str,"%3.2f\t\t\t\t\t\t%d",(flashParameters.humidityAlarms[i].lowHumidityCheck * 1.0)/ 100.0,flashParameters.humidityAlarms[i].lowHumidityAlarmValid);
                printk("I\t%s",str);
            }
            printk("\r\n");
        }
        printk("\r\n    Sensor\tHigh E\tHigh A\tHigh T\tHigh V\tHigh Time\t\t\tHigh Valid\r\n");
        for(i=0; i < MAX_NUMBER_HUMIDITY_SENSORS; i++)
        {
            printk("    %d %s\t",i,humiditySensorNames[humiditySensorsPresent[i]]);
            if(flashParameters.humidityAlarms[i].humidityAlarm & HIGHHUMIDITYENABLE)
                printk("E\t");
            else
                printk("D\t");
            if(flashParameters.humidityAlarms[i].humidityAlarm & HIGHHUMIDITYACTIVE)
            {
//                curTime = flashParameters.humidityAlarms[i].highHumidityTime + (flashParameters.timeZone * 60 * 60);
                curTime = flashParameters.humidityAlarms[i].highHumidityTime ;
                pTime = localtime(&curTime);
                sprintf(str,"%3.2f\t%3.2f\t%02d/%02d/%04d %02d:%02d:%02d", \
                (flashParameters.humidityAlarms[i].highHumidityCheck * 1.0)/ 100.0,(flashParameters.humidityAlarms[i].highHumidityAlarmValue * 1.0)/ 100.0, \
                pTime->tm_mon+1,pTime->tm_mday,pTime->tm_year + 1900,pTime->tm_hour,pTime->tm_min,pTime->tm_sec);
                printk("A\t%s\t%d",str,flashParameters.humidityAlarms[i].highHumidityAlarmValid);
            }
            else
            {
                sprintf(str,"%3.2f\t\t\t\t\t\t%d",(flashParameters.humidityAlarms[i].highHumidityCheck * 1.0)/ 100.0,flashParameters.humidityAlarms[i].highHumidityAlarmValid);
                printk("I\t%s",str);
            }
            printk("\r\n");
        }

#if 1
        printk("\r\n    Pressure Alarms Check: %d seconds\r\n",flashParameters.pressureAlarmCheck);
        printk("    Pressure Alarms Valid: %d seconds\r\n",flashParameters.pressureAlarmValid);
        printk("    Pressure Alarms\r\n    Sensor\tLow E\tLow A\tLow T\tLow V\tLow Time\t\t\tLow Valid\r\n");
        for(i=0; i < MAX_NUMBER_PRESSURE_SENSORS; i++)
        {
            printk("    %d %s\t",i,pressureSensorNames[pressureSensorsPresent[i]]);
            if(flashParameters.pressureAlarms[i].pressureAlarm & LOWPRESSUREENABLE)
                printk("E\t");
            else
                printk("D\t");
            if(flashParameters.pressureAlarms[i].pressureAlarm & LOWPRESSUREACTIVE)
            {
//                curTime = flashParameters.pressureAlarms[i].lowPressureTime + (flashParameters.timeZone * 60 * 60);
                curTime = flashParameters.pressureAlarms[i].lowPressureTime ;
                pTime = localtime(&curTime);
                sprintf(str,"%3.2f\t%3.2f\t%02d/%02d/%04d %02d:%02d:%02d", \
                (flashParameters.pressureAlarms[i].lowPressureCheck * 1.0)/ 100.0,(flashParameters.pressureAlarms[i].lowPressureAlarmValue * 1.0)/ 100.0, \
                pTime->tm_mon+1,pTime->tm_mday,pTime->tm_year + 1900,pTime->tm_hour,pTime->tm_min,pTime->tm_sec);
                printk("A\t%s\t%d",str,flashParameters.pressureAlarms[i].lowPressureAlarmValid);
            }
            else
            {
                sprintf(str,"%3.2f\t\t\t\t\t\t%d",(flashParameters.pressureAlarms[i].lowPressureCheck * 1.0)/ 100.0,flashParameters.pressureAlarms[i].lowPressureAlarmValid);
                printk("I\t%s",str);
            }
            printk("\r\n");
        }
        printk("\r\n    Sensor\tHigh E\tHigh A\tHigh T\tHigh V\tHigh Time\t\t\tHigh Valid\r\n");
        for(i=0; i < MAX_NUMBER_PRESSURE_SENSORS; i++)
        {
            printk("    %d %s\t",i,pressureSensorNames[pressureSensorsPresent[i]]);
            if(flashParameters.pressureAlarms[i].pressureAlarm & HIGHPRESSUREENABLE)
                printk("E\t");
            else
                printk("D\t");
            if(flashParameters.pressureAlarms[i].pressureAlarm & HIGHPRESSUREACTIVE)
            {
//                curTime = flashParameters.pressureAlarms[i].highPressureTime + (flashParameters.timeZone * 60 * 60);
                curTime = flashParameters.pressureAlarms[i].highPressureTime ;
                pTime = localtime(&curTime);
                sprintf(str,"%3.2f\t%3.2f\t%02d/%02d/%04d %02d:%02d:%02d", \
                (flashParameters.pressureAlarms[i].highPressureCheck * 1.0)/ 100.0,(flashParameters.pressureAlarms[i].highPressureAlarmValue * 1.0)/ 100.0, \
                pTime->tm_mon+1,pTime->tm_mday,pTime->tm_year + 1900,pTime->tm_hour,pTime->tm_min,pTime->tm_sec);
                printk("A\t%s\t%d",str,flashParameters.pressureAlarms[i].highPressureAlarmValid);
            }
            else
            {
                sprintf(str,"%3.2f\t\t\t\t\t\t%d",(flashParameters.pressureAlarms[i].highPressureCheck * 1.0)/ 100.0,flashParameters.pressureAlarms[i].highPressureAlarmValid);
                printk("I\t%s",str);
            }
            printk("\r\n");
        }

        printk("\r\n    EZOEC Alarms Check: %d seconds\r\n",flashParameters.ezoecAlarmCheck);
        printk("    EZOEC Alarms Valid: %d seconds\r\n",flashParameters.ezoecAlarmValid);
        printk("    EZOEC Alarms\r\n    Sensor\tLow E\tLow A\tLow T\tLow V\tLow Time\t\t\tLow Valid\r\n");
        for(i=0; i < MAX_NUMBER_EZOEC_SENSORS; i++)
        {
            printk("    %d %s\t",i,ezoecSensorNames[ezoecSensorsPresent[i]]);
            if(flashParameters.ezoecAlarms[i].ezoecAlarm & LOWEZOECENABLE)
                printk("E\t");
            else
                printk("D\t");
            if(flashParameters.ezoecAlarms[i].ezoecAlarm & LOWEZOECACTIVE)
            {
//                curTime = flashParameters.ezoecAlarms[i].lowezoecTime + (flashParameters.timeZone * 60 * 60);
                curTime = flashParameters.ezoecAlarms[i].lowezoecTime ;
                pTime = localtime(&curTime);
                sprintf(str,"%3.2f\t%3.2f\t%02d/%02d/%04d %02d:%02d:%02d", \
                (flashParameters.ezoecAlarms[i].lowezoecCheck * 1.0)/ 100.0,(flashParameters.ezoecAlarms[i].lowezoecAlarmValue * 1.0)/ 100.0, \
                pTime->tm_mon+1,pTime->tm_mday,pTime->tm_year + 1900,pTime->tm_hour,pTime->tm_min,pTime->tm_sec);
                printk("A\t%s\t%d",str,flashParameters.ezoecAlarms[i].lowezoecAlarmValid);
            }
            else
            {
                sprintf(str,"%3.2f\t\t\t\t\t\t%d",(flashParameters.ezoecAlarms[i].lowezoecCheck * 1.0)/ 100.0,flashParameters.ezoecAlarms[i].lowezoecAlarmValid);
                printk("I\t%s",str);
            }
            printk("\r\n");
        }
        printk("\r\n    Sensor\tHigh E\tHigh A\tHigh T\tHigh V\tHigh Time\t\t\tHigh Valid\r\n");
        for(i=0; i < MAX_NUMBER_EZOEC_SENSORS; i++)
        {
            printk("    %d %s\t",i,ezoecSensorNames[ezoecSensorsPresent[i]]);
            if(flashParameters.ezoecAlarms[i].ezoecAlarm & HIGHEZOECENABLE)
                printk("E\t");
            else
                printk("D\t");
            if(flashParameters.ezoecAlarms[i].ezoecAlarm & HIGHEZOECACTIVE)
            {
//                curTime = flashParameters.ezoecAlarms[i].highezoecTime + (flashParameters.timeZone * 60 * 60);
                curTime = flashParameters.ezoecAlarms[i].highezoecTime ;
                pTime = localtime(&curTime);
                sprintf(str,"%3.2f\t%3.2f\t%02d/%02d/%04d %02d:%02d:%02d", \
                (flashParameters.ezoecAlarms[i].highezoecCheck * 1.0)/ 100.0,(flashParameters.ezoecAlarms[i].highezoecAlarmValue * 1.0)/ 100.0, \
                pTime->tm_mon+1,pTime->tm_mday,pTime->tm_year + 1900,pTime->tm_hour,pTime->tm_min,pTime->tm_sec);
                printk("A\t%s\t%d",str,flashParameters.ezoecAlarms[i].highezoecAlarmValid);
            }
            else
            {
                sprintf(str,"%3.2f\t\t\t\t\t\t%d",(flashParameters.ezoecAlarms[i].highezoecCheck * 1.0)/ 100.0,flashParameters.ezoecAlarms[i].highezoecAlarmValid);
                printk("I\t%s",str);
            }
            printk("\r\n");
        }


        printk("\r\n    Power Alarm Check: %d seconds\r\n",flashParameters.powerAlarmCheck);
        printk("    Power Alarm Valid: %d seconds\r\n",flashParameters.powerAlarmValid);
        printk("    Power Alarm\r\n    Sensor\tE\tA\tTime\r\n");
        for(i=0; i < MAX_NUMBER_POWER_SENSORS; i++)
        {
            printk("    %d",i);
            if(flashParameters.powerAlarms[i].powerAlarm &POWERENABLE)
                printk("\t\tE\t");
            else
                printk("\t\tD\t");
            if(flashParameters.powerAlarms[i].powerAlarm & POWERACTIVE)
            {
//                curTime = flashParameters.powerAlarms[i].powerTime + (flashParameters.timeZone * 60 * 60);
                curTime = flashParameters.powerAlarms[i].powerTime ;
                pTime = localtime(&curTime);
                sprintf(str,"%02d/%02d/%04d %02d:%02d:%02d", \
                pTime->tm_mon+1,pTime->tm_mday,pTime->tm_year + 1900,pTime->tm_hour,pTime->tm_min,pTime->tm_sec);
                printk("A\t%s",str);
            }
            else
            {
                printk("I");
            }
            printk("\r\n");
        }
#endif
    }
    else
    {
        printk("Flash Parameter Key: 0x%08X Not Set\r\n",flashParameters.key);
    }
#endif
}

/*!
 * \fn void setFlashxParameters(uint8_t display)
 *
 * \brief loads the NV Flash parameters from teh RAM flash parameters
 *
 * \param display true to display parameters after the write, false to not display after a write
 *
 * \return none
 */
void setFlashxParameters(uint8_t display)
{
    //    int i;
    //    uint16_t address = FLASHPARAMETERSTART;
    //    uint8_t tmp[256];
    //    uint8_t *pFlashParameters = (uint8_t *)&flashParameters;

    /* erase page */
    flashxEraseSector(FLASHPARAMETERSTART);
    k_sleep(K_MSEC(200));

    //    flashParameters.key = FLASHPARAMETERKEY;
    //    if(sizeof(flashParametersStruct) <= 256)
    //    {
    //        memcpy(tmp,pFlashParameters,sizeof(flashParametersStruct));
    //        flashxWritePage(FLASHPARAMETERSTART, address,tmp,sizeof(flashParametersStruct));
    //    }
    //    else if(sizeof(flashParametersStruct) <= 512)
    //    {
    //        memcpy(tmp,pFlashParameters,256);
    //        flashxWritePage(FLASHPARAMETERSTART, address,tmp,256);
    //        memcpy(tmp,pFlashParameters+256,sizeof(flashParametersStruct) - 256);
    //        flashxWritePage(FLASHPARAMETERSTART+1, address,tmp,(uint16_t)(sizeof(flashParametersStruct)-256));
    //    }
    //   else if(sizeof(flashParametersStruct) <= 768)
    //    {
    //        memcpy(tmp,pFlashParameters,256);
    //        flashxWritePage(FLASHPARAMETERSTART, address,tmp,256);
    //        memcpy(tmp,pFlashParameters+256,256);
    //        flashxWritePage(FLASHPARAMETERSTART+1, address,tmp,256);
    //        memcpy(tmp,pFlashParameters+512,sizeof(flashParametersStruct) - 512);
    //        flashxWritePage(FLASHPARAMETERSTART+2, address,tmp,(uint16_t)(sizeof(flashParametersStruct)-512));
    //    }
    //    else
    //    {
    //        memcpy(tmp,pFlashParameters,256);
    //        flashxWritePage(FLASHPARAMETERSTART, address,tmp,256);
    //        memcpy(tmp,pFlashParameters+256,256);
    //        flashxWritePage(FLASHPARAMETERSTART+1, address,tmp,256);
    //        memcpy(tmp,pFlashParameters+512,256);
    //        flashxWritePage(FLASHPARAMETERSTART+2, address,tmp,256);
    //        memcpy(tmp,pFlashParameters+768,sizeof(flashParametersStruct) - 768);
    //        flashxWritePage(FLASHPARAMETERSTART+3, address,tmp,(uint16_t)(sizeof(flashParametersStruct)-512));
    //    }
    ////    for(i=0; i < sizeof(flashParametersStruct); i++)
    ////    	PRINTF("%02X %02X\r\n",tmp[i],pFlashParameters[i]);
    ////        for(i=0; i < sizeof(flashParametersStruct); i++,address++)
    ////    {
    ////        PRINTF("i: %d %02X %02X\r\n",i,address,tmp[i]);
    ////    flashxWritePage(FLASHPARAMETERSTART, address,tmp,256);
    ////    }
    //    if(!flashParameters.silent)
    //        printk("Flash Parameters Set\r\n");
    //    if(display)
    //    {
    //        displayFlashxParameters();
    //    }
    ////	publishSensor = true;
}

/*!
 * \fn int initW25Q64JV( void)
 *
 * \brief Initiailizes the W25Q64JW.
 *
 *  This will read the WHO_AM_I value to determine if a W25Q64JW is connected.\n
 *  It will set SENSORTYPEW25Q64JW if a W25Q64JW is available.
 *
 *
 * \return TRUE if W25Q64JW connected, FALSE if W25Q64JW not connected.
 */
int initW25Q64JV(void)
{
    uint8_t flashIDIn[5];

    readNVFlashxID(flashIDIn);
    if ((flashIDIn[0] == W25Q64JW_WHO_AM_I_REG0) &&
        (flashIDIn[1] == W25Q64JW_WHO_AM_I_REG1) &&
        (flashIDIn[2] == W25Q64JW_WHO_AM_I_REG2))
    {
        sensorTypePresentAll |= (1 << SENSORTYPEW25Q64JV);
        myPrintkI("W25Q64JV 64MB Flash Memory - Present\r\n");
        return TRUE;
    }
    else
    {
        myPrintkW("W25Q64JV 64MB Flash Memory - Not Present\r\n");
        return FALSE;
    }
}
