#include "flash_dev_x25.h"

t_flash_errs flash_x25_read_uid(t_flash_iface *iface, unsigned char *uid) {
    return flash_exec_cmd_addr(iface, FLASH_X25_CMD_CMD_READ_UID, 0, 1, NULL, uid, iface->flash_info->uid.bitlen >> 3, FLASH_FLAGS_FLUSH);
}


t_flash_errs flash_x25_get_status16_2cmd(t_flash_iface *iface, unsigned int *status) {
    unsigned char status1, status2;
    t_flash_errs err = FLASH_ERR_OK;

    err = flash_get_status(iface, &status1);
    if (!err) {
        unsigned char cmd = FLASH_X25_CMD_READ_STATUS2;
        err = flash_exec_cmd(iface, &cmd, 1, NULL,0, &status2, 1, FLASH_FLAGS_FLUSH);
    }

    if (!err && (status != NULL))  {
        *status = (status2 << 8) | status1;
    }
    return err;
}

t_flash_errs flash_x25_get_status24_3cmd(t_flash_iface *iface, unsigned int *status) {
    unsigned char status1, status2, status3;
    t_flash_errs err = FLASH_ERR_OK;

    err = flash_get_status(iface, &status1);
    if (!err) {
        unsigned char cmd = FLASH_X25_CMD_READ_STATUS2;
        err = flash_exec_cmd(iface, &cmd, 1, NULL,0, &status2, 1, FLASH_FLAGS_FLUSH);
    }
    if (!err) {
        unsigned char cmd = FLASH_X25_CMD_READ_STATUS3;
        err = flash_exec_cmd(iface, &cmd, 1, NULL,0, &status3, 1, FLASH_FLAGS_FLUSH);
    }

    if (!err && (status != NULL))  {
        *status = (status3 << 16) | (status2 << 8) | status1;
    }
    return err;
}

t_flash_errs flash_x25_set_status16_1cmd(t_flash_iface *iface, unsigned int status, unsigned int flags) {
    t_flash_errs err = 0;
    err = flash_x25_status_write_en(iface, flags);

    if (!err) {
        unsigned char cmd = FLASH_CMD_CODE_WRITE_STATUS;
        unsigned char status_bytes[2] = {status & 0xFF, (status >> 8) & 0xFF};
        err = flash_exec_cmd(iface, &cmd, 1, status_bytes, 2, NULL, 0, FLASH_FLAGS_FLUSH);
    }

    if (!err) {
        err = flash_wait_ready(iface, iface->flash_info->status_ex.nv_wr_tout, NULL);
    }
    return err;
}

t_flash_errs flash_x25_set_status24_1cmd(t_flash_iface *iface, unsigned int status, unsigned int flags) {
    t_flash_errs err = 0;
    err = flash_x25_status_write_en(iface, flags);

    if (!err) {
        unsigned char cmd = FLASH_CMD_CODE_WRITE_STATUS;
        unsigned char status_bytes[3] = {status & 0xFF, (status >> 8) & 0xFF, (status >> 16) & 0xFF};
        err = flash_exec_cmd(iface, &cmd, 1, status_bytes, 3, NULL, 0, FLASH_FLAGS_FLUSH);
    }

    if (!err) {
        err = flash_wait_ready(iface, iface->flash_info->status_ex.nv_wr_tout, NULL);
    }
    return err;
}

t_flash_errs flash_x25_set_status24_3cmd(t_flash_iface *iface, unsigned int status,unsigned int flags) {
    t_flash_errs err = FLASH_ERR_OK;


    const unsigned char cmds[] = {FLASH_CMD_CODE_WRITE_STATUS, FLASH_X25_CMD_WRITE_STATUS2, FLASH_X25_CMD_WRITE_STATUS3};
    const unsigned char data[] = {status & 0xFF, (status >> 8) & 0xFF, (status >> 16) & 0xFF};

    for (unsigned i = 0; (i < sizeof(cmds)/sizeof(cmds[0])) && !err; ++i) {
        err = flash_x25_status_write_en(iface, flags);
        if (!err) {
            err = flash_exec_cmd(iface, &cmds[i], 1, &data[i], 1, NULL, 0, FLASH_FLAGS_FLUSH);
        }
        if (!err) {
            err = flash_wait_ready(iface, iface->flash_info->status_ex.nv_wr_tout, NULL);
        }
    }
    return err;
}


t_flash_errs flash_x25_status_write_en(t_flash_iface *iface, unsigned flags) {
    unsigned char cmd = flags & FLASH_SET_STATUS_FLAG_VOLATILE ? FLASH_X25_CMD_WR_EN_STATUS_VOLATILE : FLASH_CMD_CODE_WRITE_ENABLE;
    return flash_exec_cmd_only(iface, &cmd, 1, 0);
}
