/****************************************************************************1* Genesis Plus2* Microwire Serial EEPROM (93C46 only) support3*4* Copyright (C) 2011 Eke-Eke (Genesis Plus GX)5*6* Redistribution and use of this code or any derivative works are permitted7* provided that the following conditions are met:8*9* - Redistributions may not be sold, nor may they be used in a commercial10* product or activity.11*12* - Redistributions that are modified from the original source must include the13* complete source code, including the source code for all components used by a14* binary built from the modified sources. However, as a special exception, the15* source code distributed need not include anything that is normally distributed16* (in either source or binary form) with the major components (compiler, kernel,17* and so on) of the operating system on which the executable runs, unless that18* component itself accompanies the executable.19*20* - Redistributions must reproduce the above copyright notice, this list of21* conditions and the following disclaimer in the documentation and/or other22* materials provided with the distribution.23*24* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"25* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE26* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE27* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE28* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR29* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF30* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS31* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN32* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)33* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE34* POSSIBILITY OF SUCH DAMAGE.35*36****************************************************************************************/3738#include "shared.h"39#include "eeprom_93c.h"4041/* fixed board implementation */42#define BIT_DATA (0)43#define BIT_CLK (1)44#define BIT_CS (2)454647T_EEPROM_93C eeprom_93c;4849void eeprom_93c_init()50{51/* default eeprom state */52memset(&eeprom_93c, 0, sizeof(T_EEPROM_93C));53eeprom_93c.data = 1;54eeprom_93c.state = WAIT_START93;55sram.custom = 3;56}5758void eeprom_93c_write(unsigned char data)59{60/* Make sure CS is HIGH */61if (data & (1 << BIT_CS))62{63/* Data latched on CLK postive edge */64if ((data & (1 << BIT_CLK)) && !eeprom_93c.clk)65{66/* Current EEPROM state */67switch (eeprom_93c.state)68{69case WAIT_START93:70{71/* Wait for START bit */72if (data & (1 << BIT_DATA))73{74eeprom_93c.opcode = 0;75eeprom_93c.cycles = 0;76eeprom_93c.state = GET_OPCODE93;77}78break;79}8081case GET_OPCODE93:82{83/* 8-bit buffer (opcode + address) */84eeprom_93c.opcode |= ((data >> BIT_DATA) & 1) << (7 - eeprom_93c.cycles);85eeprom_93c.cycles++;8687if (eeprom_93c.cycles == 8)88{89/* Decode instruction */90switch ((eeprom_93c.opcode >> 6) & 3)91{92case 1:93{94/* WRITE */95eeprom_93c.buffer = 0;96eeprom_93c.cycles = 0;97eeprom_93c.state = WRITE_WORD93;98break;99}100101case 2:102{103/* READ */104eeprom_93c.buffer = *(uint16 *)(sram.sram + ((eeprom_93c.opcode & 0x3F) << 1));105eeprom_93c.cycles = 0;106eeprom_93c.state = READ_WORD93;107108/* Force DATA OUT */109eeprom_93c.data = 0;110break;111}112113case 3:114{115/* ERASE */116if (eeprom_93c.we)117{118*(uint16 *)(sram.sram + ((eeprom_93c.opcode & 0x3F) << 1)) = 0xFFFF;119}120121/* wait for next command */122eeprom_93c.state = WAIT_STANDBY93;123break;124}125126default:127{128/* special command */129switch ((eeprom_93c.opcode >> 4) & 3)130{131case 1:132{133/* WRITE ALL */134eeprom_93c.buffer = 0;135eeprom_93c.cycles = 0;136eeprom_93c.state = WRITE_WORD93;137break;138}139140case 2:141{142/* ERASE ALL */143if (eeprom_93c.we)144{145memset(sram.sram, 0xFF, 128);146}147148/* wait for next command */149eeprom_93c.state = WAIT_STANDBY93;150break;151}152153default:154{155/* WRITE ENABLE/DISABLE */156eeprom_93c.we = (eeprom_93c.opcode >> 4) & 1;157158/* wait for next command */159eeprom_93c.state = WAIT_STANDBY93;160break;161}162}163break;164}165}166}167break;168}169170case WRITE_WORD93:171{172/* 16-bit data buffer */173eeprom_93c.buffer |= ((data >> BIT_DATA) & 1) << (15 - eeprom_93c.cycles);174eeprom_93c.cycles++;175176if (eeprom_93c.cycles == 16)177{178/* check EEPROM write protection */179if (eeprom_93c.we)180{181if (eeprom_93c.opcode & 0x40)182{183/* write one word */184*(uint16 *)(sram.sram + ((eeprom_93c.opcode & 0x3F) << 1)) = eeprom_93c.buffer;185}186else187{188/* write 64 words */189int i;190for (i=0; i<64; i++)191{192*(uint16 *)(sram.sram + (i << 1)) = eeprom_93c.buffer;193194}195}196}197198/* wait for next command */199eeprom_93c.state = WAIT_STANDBY93;200}201break;202}203204case READ_WORD93:205{206/* set DATA OUT */207eeprom_93c.data = ((eeprom_93c.buffer >> (15 - eeprom_93c.cycles)) & 1);208eeprom_93c.cycles++;209210if (eeprom_93c.cycles == 16)211{212/* read next word (93C46B) */213eeprom_93c.opcode++;214eeprom_93c.cycles = 0;215eeprom_93c.buffer = *(uint16 *)(sram.sram + ((eeprom_93c.opcode & 0x3F) << 1));216}217break;218}219220default:221{222/* wait for STANDBY mode */223break;224}225}226}227}228else229{230/* CS HIGH->LOW transition */231if (eeprom_93c.cs)232{233/* standby mode */234eeprom_93c.data = 1;235eeprom_93c.state = WAIT_START93;236}237}238239/* Update input lines */240eeprom_93c.cs = (data >> BIT_CS) & 1;241eeprom_93c.clk = (data >> BIT_CLK) & 1;242}243244unsigned char eeprom_93c_read(void)245{246return ((eeprom_93c.cs << BIT_CS) | (eeprom_93c.data << BIT_DATA) | (1 << BIT_CLK));247}248249250251