273 lines
7.0 KiB
C
273 lines
7.0 KiB
C
/*
|
|
93Cx6.c - Library for the Three-wire Serial EEPROM chip
|
|
*/
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "driver/gpio.h"
|
|
#include "esp_log.h"
|
|
|
|
#include "93Cx6.h"
|
|
|
|
#define DELAY_CS 0
|
|
#define DELAY_READ 1
|
|
#define DELAY_WRITE 1
|
|
#define DELAY_WAIT 1
|
|
|
|
#define _DEBUG_ 0
|
|
|
|
enum OP { // Operations
|
|
CONTROL = 0x00,
|
|
WRITE = 0x01,
|
|
READ = 0x02,
|
|
ERASE = 0x03
|
|
};
|
|
enum CC { // Control Codes
|
|
EW_DISABLE = 0x00,
|
|
WRITE_ALL = 0x01,
|
|
ERASE_ALL = 0x02,
|
|
EW_ENABLE = 0x03
|
|
};
|
|
|
|
// Open Memory Device
|
|
// model:EEPROM model(46/56/66/76/86)
|
|
// org:Organization Select(1=8Bit/2=16Bit)
|
|
int eeprom_open(EEPROM_T * dev, int16_t model, int16_t org, int16_t GPIO_CS, int16_t GPIO_SK, int16_t GPIO_DI, int16_t GPIO_DO)
|
|
{
|
|
ESP_LOGI(__FUNCTION__, "GPIO_CS=%d",GPIO_CS);
|
|
//gpio_pad_select_gpio( GPIO_CS );
|
|
gpio_reset_pin( GPIO_CS );
|
|
gpio_set_direction( GPIO_CS, GPIO_MODE_OUTPUT );
|
|
gpio_set_level( GPIO_CS, LOW );
|
|
|
|
ESP_LOGI(__FUNCTION__, "GPIO_SK=%d",GPIO_SK);
|
|
//gpio_pad_select_gpio( GPIO_SK );
|
|
gpio_reset_pin( GPIO_SK );
|
|
gpio_set_direction( GPIO_SK, GPIO_MODE_OUTPUT );
|
|
|
|
ESP_LOGI(__FUNCTION__, "GPIO_DI=%d",GPIO_DI);
|
|
//gpio_pad_select_gpio( GPIO_DI );
|
|
gpio_reset_pin( GPIO_DI );
|
|
gpio_set_direction( GPIO_DI, GPIO_MODE_OUTPUT );
|
|
|
|
ESP_LOGI(__FUNCTION__, "GPIO_DO=%d",GPIO_DO);
|
|
//gpio_pad_select_gpio( GPIO_DO );
|
|
gpio_reset_pin( GPIO_DO );
|
|
gpio_set_direction( GPIO_DO, GPIO_MODE_INPUT );
|
|
|
|
dev->_CS = GPIO_CS;
|
|
dev->_SK = GPIO_SK;
|
|
dev->_DI = GPIO_DI;
|
|
dev->_DO = GPIO_DO;
|
|
dev->_ew = false;
|
|
dev->_org = org;
|
|
dev->_model = model;
|
|
dev->_bytes = getBytesByModel(dev->_org, dev->_model);
|
|
dev->_addr = getAddrByModel(dev->_org, dev->_model);
|
|
dev->_mask = getMaskByModel(dev->_org, dev->_model);
|
|
ESP_LOGI(__FUNCTION__, "dev->_bytes=%d dev->_addr=%d dev->_mask=%x", dev->_bytes, dev->_addr, dev->_mask);
|
|
return dev->_bytes;
|
|
};
|
|
|
|
|
|
// Erase/Write Enable
|
|
// Required Clock Cycle : 9-13
|
|
void eeprom_ew_enable(EEPROM_T *dev)
|
|
{
|
|
gpio_set_level(dev->_CS, HIGH);
|
|
usleep(DELAY_CS);
|
|
send_bits(dev, HIGH, 1);
|
|
//uint16_t value = CONTROL<<dev->_addr | EW_ENABLE<<(dev->_addr-2);
|
|
//ESP_LOGI(__FUNCTION__, "eeprom_ew_enable value=%04x", value);
|
|
send_bits(dev, CONTROL<<dev->_addr | EW_ENABLE<<(dev->_addr-2), dev->_addr + 2);
|
|
gpio_set_level(dev->_CS, LOW);
|
|
dev->_ew = true;
|
|
};
|
|
|
|
// Erase/Write Disable
|
|
// Required Clock Cycle : 9-13
|
|
void eeprom_ew_disable(EEPROM_T *dev)
|
|
{
|
|
gpio_set_level(dev->_CS, HIGH);
|
|
usleep(DELAY_CS);
|
|
send_bits(dev, HIGH, 1);
|
|
send_bits(dev, CONTROL<<dev->_addr | EW_DISABLE<<(dev->_addr-2), dev->_addr + 2);
|
|
gpio_set_level(dev->_CS, LOW);
|
|
dev->_ew = false;
|
|
}
|
|
|
|
// Check Erase/Write Enable
|
|
bool eeprom_is_ew_enabled(EEPROM_T *dev)
|
|
{
|
|
return dev->_ew;
|
|
}
|
|
|
|
// Erase All Memory
|
|
// Required Clock Cycle : 9-13
|
|
void eeprom_erase_all(EEPROM_T *dev)
|
|
{
|
|
if(!eeprom_is_ew_enabled(dev)) return;
|
|
gpio_set_level(dev->_CS, HIGH);
|
|
usleep(DELAY_CS);
|
|
send_bits(dev, HIGH, 1);
|
|
//uint16_t value = CONTROL<<dev->_addr | ERASE_ALL<<(dev->_addr-2);
|
|
//ESP_LOGI(__FUNCTION__, "eeprom_erase_all value=%04x", value);
|
|
send_bits(dev, CONTROL<<dev->_addr | ERASE_ALL<<(dev->_addr-2), dev->_addr + 2);
|
|
gpio_set_level(dev->_CS, LOW);
|
|
wait_ready(dev);
|
|
}
|
|
|
|
// Erase Byte or Word
|
|
// Required Clock Cycle : 9-13
|
|
void eeprom_erase(EEPROM_T *dev, uint16_t addr)
|
|
{
|
|
if(!eeprom_is_ew_enabled(dev)) return;
|
|
gpio_set_level(dev->_CS, HIGH);
|
|
usleep(DELAY_CS);
|
|
send_bits(dev, HIGH, 1);
|
|
if(dev->_org == EEPROM_MODE_16BIT) {
|
|
send_bits(dev, ERASE<<dev->_addr | (addr & dev->_mask), dev->_addr + 2);
|
|
} else {
|
|
send_bits(dev, ERASE<<dev->_addr | (addr & dev->_mask), dev->_addr + 2);
|
|
}
|
|
|
|
gpio_set_level(dev->_CS, LOW);
|
|
wait_ready(dev);
|
|
}
|
|
|
|
|
|
// Write All Memory with same Data
|
|
// Required Clock Cycle : 25-29
|
|
void eeprom_write_all(EEPROM_T *dev, uint16_t value)
|
|
{
|
|
if(!eeprom_is_ew_enabled(dev)) return;
|
|
gpio_set_level(dev->_CS, HIGH);
|
|
usleep(DELAY_CS);
|
|
send_bits(dev, HIGH, 1);
|
|
send_bits(dev, CONTROL<<dev->_addr | WRITE_ALL<<(dev->_addr-2), dev->_addr + 2);
|
|
if(dev->_org == EEPROM_MODE_16BIT) {
|
|
send_bits(dev, 0xFFFF & value, 16);
|
|
} else {
|
|
send_bits(dev, 0xFF & value, 8);
|
|
}
|
|
gpio_set_level(dev->_CS, LOW);
|
|
wait_ready(dev);
|
|
}
|
|
|
|
// Write Data to Memory
|
|
// Required Clock Cycle : 25-29
|
|
void eeprom_write(EEPROM_T *dev, uint16_t addr, uint16_t value)
|
|
{
|
|
if(!eeprom_is_ew_enabled(dev)) return;
|
|
gpio_set_level(dev->_CS, HIGH);
|
|
usleep(DELAY_CS);
|
|
send_bits(dev, HIGH, 1);
|
|
if(dev->_org == EEPROM_MODE_16BIT) {
|
|
send_bits(dev, WRITE<<dev->_addr | (addr & dev->_mask), dev->_addr + 2);
|
|
send_bits(dev, 0xFFFF & value, 16);
|
|
} else {
|
|
send_bits(dev, WRITE<<dev->_addr | (addr & dev->_mask), dev->_addr + 2);
|
|
send_bits(dev, 0xFF & value, 8);
|
|
}
|
|
gpio_set_level(dev->_CS, LOW);
|
|
wait_ready(dev);
|
|
}
|
|
|
|
// Read Data from Memory
|
|
uint16_t eeprom_read(EEPROM_T *dev, uint16_t addr)
|
|
{
|
|
uint16_t val = 0;
|
|
gpio_set_level(dev->_CS, HIGH);
|
|
usleep(DELAY_CS);
|
|
send_bits(dev, HIGH, 1); // Start bit
|
|
|
|
int amtBits;
|
|
if(dev->_org == EEPROM_MODE_16BIT) {
|
|
send_bits(dev, READ<<dev->_addr | (addr & dev->_mask), dev->_addr + 2);
|
|
amtBits = 16;
|
|
} else {
|
|
send_bits(dev, READ<<dev->_addr | (addr & dev->_mask), dev->_addr + 2);
|
|
amtBits = 8;
|
|
}
|
|
// Read bits
|
|
for(int i = amtBits; i>0; i--) {
|
|
gpio_set_level(dev->_SK, HIGH);
|
|
usleep(DELAY_READ);
|
|
int in = gpio_get_level(dev->_DO) ? 1 : 0;
|
|
gpio_set_level(dev->_SK, LOW);
|
|
usleep(DELAY_READ);
|
|
val |= (in << (i-1));
|
|
}
|
|
gpio_set_level(dev->_CS, LOW);
|
|
return val;
|
|
}
|
|
|
|
|
|
void send_bits(EEPROM_T *dev, uint16_t value, int len)
|
|
{
|
|
ESP_LOGD(__FUNCTION__, "send_bits value=0x%04x len=%d",value, len);
|
|
for(int i = len-1; i>=0; i--)
|
|
{
|
|
bool toSend = (value & 1<<i);
|
|
// Send bit
|
|
if (toSend) gpio_set_level(dev->_DI, HIGH);
|
|
if (!toSend) gpio_set_level(dev->_DI, LOW);
|
|
usleep(DELAY_WRITE);
|
|
gpio_set_level(dev->_SK, HIGH);
|
|
usleep(DELAY_WRITE);
|
|
gpio_set_level(dev->_SK, LOW);
|
|
usleep(DELAY_WRITE);
|
|
}
|
|
}
|
|
|
|
void wait_ready(EEPROM_T *dev)
|
|
{
|
|
//Wait until action is done.
|
|
gpio_set_level(dev->_CS, HIGH);
|
|
while(gpio_get_level(dev->_DO) != HIGH) {
|
|
usleep(DELAY_WAIT);
|
|
//vTaskDelay(1);
|
|
}
|
|
gpio_set_level(dev->_CS, LOW);
|
|
}
|
|
|
|
|
|
int getBytesByModel(int org, int model)
|
|
{
|
|
int byte = 0;
|
|
if (org == EEPROM_MODE_8BIT) byte = 128;
|
|
if (org == EEPROM_MODE_16BIT) byte = 64;
|
|
if (model == 56) byte = byte * 2; // 256/128
|
|
if (model == 66) byte = byte * 4; // 512/256
|
|
if (model == 76) byte = byte * 8; // 1024/256
|
|
if (model == 86) byte = byte * 16; // 2048/1024
|
|
return byte;
|
|
}
|
|
|
|
int getAddrByModel(int org, int model)
|
|
{
|
|
int addr = 0;
|
|
if (org == EEPROM_MODE_8BIT) addr = 7;
|
|
if (org == EEPROM_MODE_16BIT) addr = 6;
|
|
if (model == 56) addr = addr + 2; // 9/8
|
|
if (model == 66) addr = addr + 2; // 9/8
|
|
if (model == 76) addr = addr + 4; // 11/10
|
|
if (model == 86) addr = addr + 4; // 11/10
|
|
return addr;
|
|
}
|
|
|
|
uint16_t getMaskByModel(int org, int model)
|
|
{
|
|
uint16_t mask = 0;
|
|
if (org == EEPROM_MODE_8BIT) mask = 0x7f;
|
|
if (org == EEPROM_MODE_16BIT) mask = 0x3f;
|
|
if (model == 56) mask = (mask<<2) + 0x03; // 0x1ff/0xff
|
|
if (model == 66) mask = (mask<<2) + 0x03; // 0x1ff/0xff
|
|
if (model == 76) mask = (mask<<4) + 0x0f; // 0x7ff/0x3ff
|
|
if (model == 86) mask = (mask<<4) + 0x0f; // 0x7ff/0x3ff
|
|
return mask;
|
|
}
|
|
|