#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define BATCH_MODE 0xFE
#define INTERACTIVE_MODE 0xFD
#define BATCH_ADDRESS_WRITE 0xF9
#define BATCH_WRITE_DATA 0xFC
#define BATCH_READ_DATA 0xFB
#define END_RW_CYCLE 0xFA
#define NEWLINE 0x0D
#define BATCH_ADDRESS_READ 0xF8
#define EOT 0x21
#define BAUDRATE B9600
#define PROGRAMMER_DEV "/dev/ttyUSB0"
#define WRITE_DATA 0x01 //Write mode indicator for function send_init_sequence ()
#define READ_DATA 0x02 //Read mode indicator for function send_init_sequence ()
#define PAGE_SIZE 64 //This indicates the write page size as mentioned in the EEPROM data sheet.
#define READ_SIZE 200 //This indicates how many bytes we read at one shot.
#define EEPROM_SIZE 0x7FFF //This indicates the size of the serial EEPROM. Change according to EEPROM used.
static void read_from_eeprom();
static void write_into_eeprom(FILE *fp);
static void write_byte(unsigned char cmd);
static void get_response(unsigned char wait_char);
static void get_banner();
static void copy_into_file_buff(char *buff);
static void switch_mode(unsigned char mode);
static void send_end_cycle();
static void send_init_sequence(unsigned int index, unsigned char nobytes, unsigned char mode);
static void write_byte_at_address(unsigned int index, unsigned char nobytes);static unsigned int g_index = 0;
static char *FILE_DATA_BUFF = NULL;
static int file_size = 0;
int serial_fd;
int main(int argc, char *argv[])
{
struct termios serial_old, serial_new, stdin_new, stdin_old, stdout_old;
unsigned char mode = 0;
FILE *fp = NULL; if((argc != 3) && (argc != 4))
{
printf("Improper usage!!\n\rCorrect Usage: %s -r [count]|-w hex_file_to_read_or_write\n\r",argv[0]);
exit(1);
}
if(!strcmp(argv[1],"-r"))
{
mode = READ_DATA; if((fp=fopen(argv[3],"w")) == NULL)
{
printf("Error: File doesn't exist!!\n\r");
exit(1);
}
file_size = atoi(argv[2]); if(file_size == 0)
{
file_size = EEPROM_SIZE;
}
}
else
if(!strcmp(argv[1],"-w"))
{
mode = WRITE_DATA; if((fp=fopen(argv[2],"r"))==NULL)
{
printf("Error: File doesn't exist!!\n\r");
exit(1);
}
}
#ifndef SIMULATION
serial_fd = open(PROGRAMMER_DEV, O_RDWR | O_NOCTTY);
if (serial_fd < 0)
{
perror(PROGRAMMER_DEV);
exit(1);
} tcgetattr(STDIN_FILENO, &stdin_old);
tcgetattr(STDIN_FILENO, &stdin_new); tcgetattr(serial_fd, &serial_old );
tcgetattr(serial_fd, &serial_new ); tcgetattr(STDOUT_FILENO,&stdout_old); serial_new.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
serial_new.c_iflag = IGNPAR;
serial_new.c_oflag = 0;
serial_new.c_lflag = 0;
serial_new.c_cc[VMIN]=1;
serial_new.c_cc[VTIME]=0;
tcflush(serial_fd, TCIFLUSH);
tcsetattr(serial_fd,TCSANOW,&serial_new); stdin_new.c_lflag &= ~(ICANON | ECHO);
#endif
get_banner();
if(mode == READ_DATA) {
printf("Reading from eeprom...please wait");
fflush(stdout);
read_from_eeprom();
for(g_index = 0 ; g_index < file_size ; g_index++)
{ fputc(FILE_DATA_BUFF[g_index], fp);
}
printf("\n\rReading done. Output stored in file \"%s\"\n\r", argv[3]);
fclose(fp); }
else
if(mode == WRITE_DATA)
{
printf("Writing into eeprom from file \"%s\"...please wait", argv[2]);
write_into_eeprom(fp);
printf("\n\rWriting done.\n\r");
fclose(fp);
}
close(serial_fd); if(FILE_DATA_BUFF)
{
free(FILE_DATA_BUFF);
}
#ifndef SIMULATION
tcsetattr(serial_fd, TCSANOW, &serial_old );#endif
return 0;
}
static void read_from_eeprom()
{
FILE_DATA_BUFF = malloc(file_size);
unsigned char byte = 0;
unsigned int index = 0;
if(!FILE_DATA_BUFF)
{
exit(1);
}
switch_mode(BATCH_MODE); for(index = 0; index < file_size; index++)
{
if((index%READ_SIZE) == 0)
{
send_end_cycle();
send_init_sequence(index, READ_SIZE, READ_DATA);
printf(".");
fflush(stdout);
}
write_byte(BATCH_READ_DATA);
write_byte(NEWLINE);
read(serial_fd,&byte,1);
get_response(EOT); FILE_DATA_BUFF[g_index++] = byte;
}
switch_mode(INTERACTIVE_MODE);
write_byte('s'); write_byte(NEWLINE);
return;
}
static void write_into_eeprom(FILE *fp)
{
long size = 0, index = 0, bytes_remaining = 0, no_bytes_to_write = 0;
char inp_line[80]={0};
char first_time = 1; fseek(fp, 0, SEEK_END);
size = ftell(fp);
rewind(fp); FILE_DATA_BUFF = malloc(size);
if(!FILE_DATA_BUFF)
{
printf("Memory allocation failed, exiting...\n");
exit(1);
}
while( (fgets(inp_line,80,fp)))
{
copy_into_file_buff(inp_line);
}
switch_mode(BATCH_MODE); first_time = 1;
bytes_remaining = size;
no_bytes_to_write = 0;
for(index = 0; index < size; index++)
{
if(first_time)
{
first_time = 0;
send_end_cycle();
printf(".");
fflush(stdout);
if((bytes_remaining / PAGE_SIZE) > 0)
{
no_bytes_to_write = PAGE_SIZE;
bytes_remaining = bytes_remaining - PAGE_SIZE;
}
else
{
no_bytes_to_write = bytes_remaining;
}
send_init_sequence(index, no_bytes_to_write, WRITE_DATA);
write_byte_at_address(index, no_bytes_to_write);
}
else
if(((index)%64) == 0)
{
send_end_cycle();
printf(".");
fflush(stdout);
if((bytes_remaining / PAGE_SIZE) > 0)
{
no_bytes_to_write = PAGE_SIZE;
bytes_remaining = bytes_remaining - PAGE_SIZE;
}
else
{
no_bytes_to_write = bytes_remaining;
}
send_init_sequence(index, no_bytes_to_write, WRITE_DATA);
write_byte_at_address(index, no_bytes_to_write);
}
}
switch_mode(INTERACTIVE_MODE);
}
static void send_end_cycle()
{
#ifdef SIMULATION
printf("==ENDING CYCLE==\n");
return;
#endif
write_byte(END_RW_CYCLE);
write_byte(NEWLINE);
get_response(EOT);
}
static void switch_mode(unsigned char mode)
{
#ifdef SIMULATION
return;
#endif
write_byte(mode);
write_byte(NEWLINE);
if(mode == BATCH_MODE)
{
get_response(EOT);
get_response(EOT);
}
else
if(mode == INTERACTIVE_MODE)
{ }
else
{
assert(0); }
}
static void send_init_sequence(unsigned int address, unsigned char length, unsigned char mode)
{ if(mode == WRITE_DATA)
{
write_byte(BATCH_ADDRESS_WRITE);
}
else
if(mode == READ_DATA)
{
write_byte(BATCH_ADDRESS_READ);
}
write_byte(NEWLINE);
get_response(EOT); write_byte((address) & 0xFF); write_byte((address >> 8) & 0xFF); write_byte(length);
get_response(EOT);
}
static void write_byte_at_address(unsigned int index, unsigned char length)
{
unsigned int idx = 0; write_byte(BATCH_WRITE_DATA);
write_byte(NEWLINE);
get_response(EOT);
for(idx=index; idx < index+length; idx++)
{
write_byte(FILE_DATA_BUFF[idx]);
#ifdef SIMULATION
printf("Writing byte: %c at index %d\n",FILE_DATA_BUFF[idx], idx);
#endif
}
get_response(EOT);
send_end_cycle();
return;
}
static void get_response(unsigned char wait_char)
{
unsigned char resp = 0x00;
#ifdef SIMULATION
return;
#endif
while(read(serial_fd,&resp,1))
{
if(resp == wait_char)
{
break;
}
}
}
static void write_byte(unsigned char cmd)
{#ifndef SIMULATION
write(serial_fd,&cmd,1);
#endif
}
static void get_banner()
{
#ifndef SIMULATION
get_response('>');
get_response(' ');
#endif
}
static void copy_into_file_buff(char *buff)
{
long i = 0;
while(*(buff+i) != '\0')
{
FILE_DATA_BUFF[g_index++] = *(buff + i++);
}
}