mirror of
https://github.com/McMCCRU/SNANDer
synced 2026-07-08 07:32:18 +00:00
433 lines
7.4 KiB
C
433 lines
7.4 KiB
C
/* Copyright (C) 2005-2021 Mokrushin I.V. aka McMCC mcmcc@mail.ru
|
|
A simple bitbang protocol for Microwire 8-pin serial EEPROMs
|
|
(93XX devices). Support organization 8bit and 16bit(8bit emulation).
|
|
|
|
bitbang_microwire.c
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "bitbang_microwire.h"
|
|
|
|
struct gpio_cmd bb_func;
|
|
|
|
#if 0
|
|
unsigned char ORG = 0; /* organization 0 = 8 bit and 1 = 16 bit */
|
|
#endif
|
|
unsigned char CLK = 0;
|
|
unsigned char DO = 0;
|
|
unsigned char DI = 0;
|
|
unsigned char CSEL = 0;
|
|
|
|
int org = 0;
|
|
int mw_eepromsize = 0;
|
|
int fix_addr_len = 0;
|
|
|
|
static unsigned char data = 0;
|
|
|
|
static void delay_ms(int n)
|
|
{
|
|
#if 0 /* ifndef _WINDOWS */
|
|
int i;
|
|
for(i = 0; i < (n * 100000); i++);
|
|
#else
|
|
usleep(n);
|
|
#endif
|
|
}
|
|
|
|
static void data_1()
|
|
{
|
|
data = data | DI;
|
|
if (bb_func.gpio_setbits)
|
|
bb_func.gpio_setbits(data);
|
|
}
|
|
|
|
static void data_0()
|
|
{
|
|
data = data & (~DI);
|
|
if (bb_func.gpio_setbits)
|
|
bb_func.gpio_setbits(data);
|
|
}
|
|
|
|
static void org_1()
|
|
{
|
|
#if 0
|
|
data = data | ORG; /* 16bit */
|
|
if (bb_func.gpio_setbits)
|
|
bb_func.gpio_setbits(data);
|
|
#endif
|
|
}
|
|
|
|
static void org_0()
|
|
{
|
|
#if 0
|
|
data = data & (~ORG); /* 8bit */
|
|
if (bb_func.gpio_setbits)
|
|
bb_func.gpio_setbits(data);
|
|
#endif
|
|
}
|
|
|
|
static void csel_1()
|
|
{
|
|
data = data | CSEL;
|
|
if (bb_func.gpio_setbits)
|
|
bb_func.gpio_setbits(data);
|
|
}
|
|
|
|
static void csel_0()
|
|
{
|
|
data = data & (~CSEL);
|
|
if (bb_func.gpio_setbits)
|
|
bb_func.gpio_setbits(data);
|
|
}
|
|
|
|
static void clock_1()
|
|
{
|
|
data = data | CLK;
|
|
if (bb_func.gpio_setbits)
|
|
bb_func.gpio_setbits(data);
|
|
}
|
|
|
|
static void clock_0()
|
|
{
|
|
data = data & (~CLK);
|
|
if (bb_func.gpio_setbits)
|
|
bb_func.gpio_setbits(data);
|
|
}
|
|
|
|
static unsigned int get_data()
|
|
{
|
|
unsigned char b = 0;
|
|
if (bb_func.gpio_getbits)
|
|
bb_func.gpio_getbits(&b);
|
|
return ((b & DO) == DO);
|
|
}
|
|
|
|
static int addr_nbits(const char *func, int size)
|
|
{
|
|
int i = 0;
|
|
|
|
if (fix_addr_len) {
|
|
printf("%s: Set address len %d bits\n", func, fix_addr_len);
|
|
return fix_addr_len;
|
|
}
|
|
|
|
switch (size) {
|
|
case 128: /* 93c46 */
|
|
i = org ? 6 : 7;
|
|
break;
|
|
case 256: /* 93c56 */
|
|
case 512: /* 93c66 */
|
|
i = org ? 8 : 9;
|
|
break;
|
|
case 1024: /* 93c76 */
|
|
case 2048: /* 93c86 */
|
|
i = org ? 10 : 11;
|
|
break;
|
|
case 4096: /* 93c96(not original name) */
|
|
i = org ? 12 : 13;
|
|
break;
|
|
default:
|
|
i = 6; /* 93c06 and 93c16(not original name) */
|
|
break;
|
|
}
|
|
|
|
printf("%s: Set address len %d bits\n", func, i);
|
|
|
|
return i;
|
|
}
|
|
|
|
static int convert_size(int eeprom_size)
|
|
{
|
|
int k = 1;
|
|
|
|
org_0();
|
|
delay_ms(1);
|
|
if (org)
|
|
{
|
|
org_1();
|
|
delay_ms(1);
|
|
k = 2;
|
|
}
|
|
eeprom_size = eeprom_size / k;
|
|
|
|
return eeprom_size;
|
|
}
|
|
|
|
static void send_to_di(unsigned int val, int nbit)
|
|
{
|
|
int b = 0, i = 0;
|
|
|
|
while (i < nbit)
|
|
{
|
|
b = val & (1 << ((nbit - i++) - 1));
|
|
clock_0();
|
|
if (b)
|
|
data_1();
|
|
else
|
|
data_0();
|
|
delay_ms(1);
|
|
clock_1();
|
|
delay_ms(1);
|
|
}
|
|
}
|
|
|
|
static unsigned char get_from_do()
|
|
{
|
|
unsigned char val = 0;
|
|
int b = 0, i = 0;
|
|
while (i < 8)
|
|
{
|
|
clock_0();
|
|
delay_ms(1);
|
|
b = get_data();
|
|
clock_1();
|
|
delay_ms(1);
|
|
val |= (b << (7 - i++));
|
|
}
|
|
return val;
|
|
}
|
|
|
|
static void enable_write_3wire(int num_bit)
|
|
{
|
|
csel_0();
|
|
clock_0();
|
|
delay_ms(1);
|
|
data_1();
|
|
csel_1();
|
|
delay_ms(1);
|
|
clock_1();
|
|
delay_ms(1);
|
|
|
|
send_to_di(3, 4);
|
|
send_to_di(0, num_bit - 2);
|
|
|
|
data_0();
|
|
delay_ms(1);
|
|
csel_0();
|
|
delay_ms(1);
|
|
}
|
|
|
|
static void disable_write_3wire(int num_bit)
|
|
{
|
|
csel_1();
|
|
delay_ms(1);
|
|
clock_0();
|
|
delay_ms(1);
|
|
data_1();
|
|
delay_ms(1);
|
|
clock_1();
|
|
delay_ms(1);
|
|
send_to_di(0, 4);
|
|
send_to_di(0, num_bit - 2);
|
|
csel_0();
|
|
delay_ms(1);
|
|
}
|
|
|
|
static void chip_busy(void)
|
|
{
|
|
printf("Error: Always BUSY! Communication problem...The broken microwire chip?\n");
|
|
}
|
|
|
|
void Erase_EEPROM_3wire(int size_eeprom)
|
|
{
|
|
int i, num_bit;
|
|
|
|
num_bit = addr_nbits(__func__, size_eeprom);
|
|
|
|
enable_write_3wire(num_bit);
|
|
csel_0();
|
|
clock_0();
|
|
delay_ms(1);
|
|
data_1();
|
|
csel_1();
|
|
delay_ms(1);
|
|
clock_1();
|
|
delay_ms(1);
|
|
|
|
send_to_di(2, 4);
|
|
send_to_di(0, num_bit - 2);
|
|
clock_0();
|
|
data_0();
|
|
delay_ms(1);
|
|
csel_0();
|
|
delay_ms(1);
|
|
csel_1();
|
|
delay_ms(1);
|
|
clock_1();
|
|
delay_ms(1);
|
|
i = 0;
|
|
while (!get_data() && i < 10000)
|
|
{
|
|
clock_0();
|
|
delay_ms(1);
|
|
clock_1();
|
|
delay_ms(1);
|
|
i++;
|
|
}
|
|
|
|
if (i == 10000)
|
|
{
|
|
chip_busy();
|
|
return;
|
|
}
|
|
|
|
csel_0();
|
|
delay_ms(1);
|
|
clock_0();
|
|
delay_ms(1);
|
|
clock_1();
|
|
delay_ms(1);
|
|
|
|
disable_write_3wire(num_bit);
|
|
}
|
|
|
|
int Read_EEPROM_3wire(unsigned char *buffer, int size_eeprom)
|
|
{
|
|
int address, num_bit, l;
|
|
|
|
num_bit = addr_nbits(__func__, size_eeprom);
|
|
size_eeprom = convert_size(size_eeprom);
|
|
|
|
address = 0;
|
|
|
|
for (l = 0; l < size_eeprom; l++)
|
|
{
|
|
csel_0();
|
|
clock_0();
|
|
delay_ms(1);
|
|
data_1();
|
|
csel_1();
|
|
delay_ms(1);
|
|
clock_1();
|
|
delay_ms(1);
|
|
|
|
send_to_di(2, 2);
|
|
send_to_di(l, num_bit);
|
|
|
|
data_0();
|
|
clock_0();
|
|
delay_ms(1);
|
|
clock_1();
|
|
delay_ms(1);
|
|
buffer[address] = get_from_do();
|
|
if (org)
|
|
{
|
|
address++;
|
|
buffer[address] = get_from_do();
|
|
}
|
|
csel_0();
|
|
delay_ms(1);
|
|
clock_0();
|
|
delay_ms(1);
|
|
clock_1();
|
|
delay_ms(1);
|
|
printf("\bRead %d%% [%d] of [%d] bytes ", 100 * l / size_eeprom, l, size_eeprom);
|
|
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
|
|
fflush(stdout);
|
|
address++;
|
|
}
|
|
printf("Read 100%% [%d] of [%d] bytes \n", l, size_eeprom);
|
|
return 0;
|
|
}
|
|
|
|
int Write_EEPROM_3wire(unsigned char *buffer, int size_eeprom)
|
|
{
|
|
int i, l, address, num_bit;
|
|
|
|
num_bit = addr_nbits(__func__, size_eeprom);
|
|
size_eeprom = convert_size(size_eeprom);
|
|
|
|
enable_write_3wire(num_bit);
|
|
address = 0;
|
|
|
|
for (l = 0; l < size_eeprom; l++)
|
|
{
|
|
csel_0();
|
|
clock_0();
|
|
delay_ms(1);
|
|
data_1();
|
|
csel_1();
|
|
delay_ms(1);
|
|
clock_1();
|
|
delay_ms(1);
|
|
send_to_di(1, 2);
|
|
send_to_di(l, num_bit);
|
|
send_to_di(buffer[address], 8);
|
|
if (org)
|
|
{
|
|
address++;
|
|
send_to_di(buffer[address], 8);
|
|
}
|
|
clock_0();
|
|
data_0();
|
|
delay_ms(1);
|
|
csel_0();
|
|
delay_ms(1);
|
|
csel_1();
|
|
delay_ms(1);
|
|
clock_1();
|
|
delay_ms(1);
|
|
i = 0;
|
|
while (!get_data() && i < 10000)
|
|
{
|
|
clock_0();
|
|
delay_ms(1);
|
|
clock_1();
|
|
delay_ms(1);
|
|
i++;
|
|
}
|
|
if (i == 10000)
|
|
{
|
|
printf("\n");
|
|
chip_busy();
|
|
return -1;
|
|
}
|
|
|
|
csel_0();
|
|
delay_ms(1);
|
|
clock_0();
|
|
delay_ms(1);
|
|
clock_1();
|
|
delay_ms(1);
|
|
printf("\bWritten %d%% [%d] of [%d] bytes ", 100 * l / size_eeprom, l, size_eeprom);
|
|
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
|
|
fflush(stdout);
|
|
address++;
|
|
}
|
|
printf("Written 100%% [%d] of [%d] bytes \n", l, size_eeprom);
|
|
disable_write_3wire(num_bit);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int deviceSize_3wire(char *eepromname)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; mw_eepromlist[i].size; i++) {
|
|
if (strstr(mw_eepromlist[i].name, eepromname)) {
|
|
return (mw_eepromlist[i].size);
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
/* End of [bitbang_microwire.c] package */
|