#include "fram.h"

void fram_cfg_setup(fram_cfg_t *cfg) {
	cfg.sck_port = GPIOA;
    cfg->sck = GPIO_PIN_5;
    cfg.sck_port = GPIOA;
    cfg->miso = GPIO_PIN_6;
    cfg.sck_port = GPIOA;
    cfg->mosi = GPIO_PIN_7;
    cfg.sck_port = GPIOA;
    cfg->cs = GPIO_PIN_4;
    //cfg->spi_speed = 1000000; // 1 MHz
    //cfg->spi_mode = SPI_MODE_0;
    //cfg->cs_polarity = SPI_CS_ACTIVE_LOW;
}

void fram_init(fram_t *fram, SPI_HandleTypeDef *hspi, GPIO_TypeDef *cs_port, uint16_t cs_pin) {
    fram->hspi = hspi;
    fram->cs_port = cs_port;
    fram->cs_pin = cs_pin;
    HAL_GPIO_WritePin(cs_port, cs_pin, GPIO_PIN_SET);
}

void fram_write_enable(fram_t *fram) {
    uint8_t cmd = FRAM_WREN;
    HAL_GPIO_WritePin(fram->cs_port, fram->cs_pin, GPIO_PIN_RESET);
    HAL_SPI_Transmit(fram->hspi, &cmd, 1, HAL_MAX_DELAY);
    HAL_GPIO_WritePin(fram->cs_port, fram->cs_pin, GPIO_PIN_SET);
}

void fram_write_disable(fram_t *fram) {
    uint8_t cmd = FRAM_WRDI;
    HAL_GPIO_WritePin(fram->cs_port, fram->cs_pin, GPIO_PIN_RESET);
    HAL_SPI_Transmit(fram->hspi, &cmd, 1, HAL_MAX_DELAY);
    HAL_GPIO_WritePin(fram->cs_port, fram->cs_pin, GPIO_PIN_SET);
}

uint8_t fram_read_status(fram_t *fram) {
    uint8_t cmd = FRAM_RDSR;
    uint8_t status;
    HAL_GPIO_WritePin(fram->cs_port, fram->cs_pin, GPIO_PIN_RESET);
    HAL_SPI_Transmit(fram->hspi, &cmd, 1, HAL_MAX_DELAY);
    HAL_SPI_Receive(fram->hspi, &status, 1, HAL_MAX_DELAY);
    HAL_GPIO_WritePin(fram->cs_port, fram->cs_pin, GPIO_PIN_SET);
    return status;
}

void fram_write_status(fram_t *fram, uint8_t value) {
    uint8_t cmd[2] = { FRAM_WRSR, value };
    fram_write_enable(fram);
    HAL_GPIO_WritePin(fram->cs_port, fram->cs_pin, GPIO_PIN_RESET);
    HAL_SPI_Transmit(fram->hspi, cmd, 2, HAL_MAX_DELAY);
    HAL_GPIO_WritePin(fram->cs_port, fram->cs_pin, GPIO_PIN_SET);
    fram_write_disable(fram);
}

void fram_read(fram_t *fram, uint16_t address, uint8_t *buffer, uint16_t count) {
    uint8_t cmd[3] = { FRAM_READ, (uint8_t)(address >> 8), (uint8_t)(address & 0xFF) };
    HAL_GPIO_WritePin(fram->cs_port, fram->cs_pin, GPIO_PIN_RESET);
    HAL_SPI_Transmit(fram->hspi, cmd, 3, HAL_MAX_DELAY);
    HAL_SPI_Receive(fram->hspi, buffer, count, HAL_MAX_DELAY);
    HAL_GPIO_WritePin(fram->cs_port, fram->cs_pin, GPIO_PIN_SET);
}

void fram_write(fram_t *fram, uint16_t address, uint8_t *buffer, uint16_t count) {
    uint8_t cmd[3] = { FRAM_WRITE, (uint8_t)(address >> 8), (uint8_t)(address & 0xFF) };
    fram_write_enable(fram);
    HAL_GPIO_WritePin(fram->cs_port, fram->cs_pin, GPIO_PIN_RESET);
    HAL_SPI_Transmit(fram->hspi, cmd, 3, HAL_MAX_DELAY);
    HAL_SPI_Transmit(fram->hspi, buffer, count, HAL_MAX_DELAY);
    HAL_GPIO_WritePin(fram->cs_port, fram->cs_pin, GPIO_PIN_SET);
    fram_write_disable(fram);
}

void fram_erase_all(fram_t *fram) {
    uint8_t empty_data[FRAM_MEM_SIZE] = {0};
    fram_write(fram, 0x0000, empty_data, FRAM_MEM_SIZE);
}


