スパカセROMライタのソース


/* Name: main.c

* Author: <insert your name here>

* Copyright: <insert your copyright message here>

* License: <insert your license reference here>

avrdude -p m328p -c avrispmkII -P usb -U flash:w:main.hex:i

*/

#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

#include <avr/pgmspace.h>

PROGMEM const char mes_hello[]="SCV MONITOR ver0.2\n";

PROGMEM const char mes_xstart[]="XMODEM receive\n";

PROGMEM const char mes_xcancel[]="XMODEM aborted\n";

PROGMEM const char mes_done[]="XMODEM done\n";

PROGMEM const char mes_werror[]="Write Error\n";

PROGMEM const char mes_page[]="error! page is 0 to 7\n";

const short NOCHAR=-1;

const char BUFLENGTH=16;

int uart_test(void);

void uart_setting(void);

void sendchar(char data);

void messege(const char *mes);

void get_command();

short getchar(void);

void print(const char *mes);

void sendreturn();

void BIGLETTER(char *strp);

int hextoi(void);

int hextois(char data);

void printByte(unsigned char data);

void printShort(unsigned int data);

void printNibble(char data);

void phase(char *command);

void xmodem_down();

void dumphex(unsigned char *data,short dsize,unsigned short addr);

int blockWrite(unsigned char *data,short dsize,short addr);

int eraseChip();

void makeTable();

unsigned char rom_read(unsigned short addr);

void setOE(unsigned char x);

void setWE(unsigned char x);

void setCE(unsigned char x);

void WE_pulse(void);

void setAddr(unsigned short addr);

void setPage(unsigned char p);

void busSelect(int bus);

void setData(unsigned char x);

unsigned char readData(void);

void testwrite(unsigned short addr,unsigned char value);

char combuf[16];

unsigned char xmbuf[128];

unsigned char rTable[256];

int sComCount;

int main(void)

{

/* insert your hardware initialization here */

CLKPR=0x80;

CLKPR=0x00; //set 8MHz 1/1

uart_setting();

busSelect(0);   //SCV

sComCount=0;

combuf[0]=0;

 

makeTable();

messege(mes_hello);

//printShort(0xABCD);

 

for(;;){

/* insert your main loop code here */

//uart_test();

sendchar('>');

get_command();

BIGLETTER(combuf);

busSelect(1);   //AVR

phase(combuf);

//print(combuf);

 

 

}

return 0;   /* never reached */

}

void phase(char *command)

{

short i;

unsigned short ad;

unsigned char v;

switch (command[0]) {

case 'X':

xmodem_down();

//blockWrite(xmbuf,128,0);

//dumphex(xmbuf,128);

sendreturn();

break;

case 'A':   // for debug

/*for(i=0;i<4;i++){

testwrite((unsigned short)i,0xa5);

}*/

testwrite(0x1004,0x45);

//for(i=0;i<128;i++){xmbuf[i]=i;}

//blockWrite( xmbuf,128,0x0000);

break;

case 'D':

sComCount=2;

ad=hextoi();

dumphex(xmbuf,128,ad);

sendreturn();

break;

case 'W':

sComCount=2;

ad=hextoi();

sComCount++;

v=hextoi();

testwrite(ad,v);

sendreturn();

break;

case 'P':

sComCount=2;

v=hextoi();

if ( (v & 7)==v){

setPage(v);

}else{

messege(mes_page);

}

sendreturn();

break;

case 'E':

eraseChip();

default:

break;

}

}

// XMODEM受信

// チェックサムは処理してないです

void xmodem_down()

{

short rdata;

short i;

unsigned char sector,xsector;

unsigned short romaddr;

romaddr=0;

xsector=255;

messege(mes_xstart);

while ( (rdata=getchar())==NOCHAR)

{

//_delay_ms(500);

sendchar(0x15); //NAK

}

while(1){

if (rdata == 0x04) {

sendchar(0x06); //ACK

messege(mes_done);

return;

}

if (rdata != 0x01) {

messege(mes_xcancel);

return;

}

while ( (rdata=getchar())==NOCHAR);

sector=(unsigned char)rdata;

while ( (rdata=getchar())==NOCHAR);

for (i=0;i<128;i++){

while ( (rdata=getchar())==NOCHAR);

xmbuf[i]=rdata;

if (xsector != sector){

testwrite(romaddr,rTable[rdata]);   //回路ミスでSCV側DBUS反転してるので対策

romaddr++;

}

}

xsector=sector;

while ( (rdata=getchar())==NOCHAR); //cksum

//blockWrite(xmbuf,128,romaddr);

//romaddr+=128;

sendchar(0x06); //ACK

while ( (rdata=getchar())==NOCHAR); //next status

}

}

void dumphex(unsigned char *data,short dsize,unsigned short addr)

{

char bytecount;

short ofst;

ofst=addr;

bytecount=0;

 

while(dsize>0)

{

if (bytecount==0){

sendreturn();

printShort((unsigned short)ofst);

sendchar(0x20);

}

printByte(rTable[rom_read(ofst)]);

//printByte(xmbuf[ofst]);

sendchar(0x20);

ofst++;

bytecount++;

if (bytecount>15){

bytecount=0;

}

dsize--;

}

}

void testwrite(unsigned short addr,unsigned char value)

{

unsigned char d;

setOE(1);

setWE(1);

setCE(0);

setAddr(0x0555);

setData(0xAA);

WE_pulse();

setAddr(0x0AAA);

setData(0x55);

WE_pulse();

setAddr(0x0555);

setData(0xA0);

WE_pulse();

setAddr(addr);

setData(value);

WE_pulse();

goto skip1;

setOE(0);

d=value & 0x80;

while (1) {

if ( (readData()& 0x80) ==d ){

break;

}

if (readData() & 0x20){

if ( (readData()& 0x80) ==d ){

break;

}else{

setOE(1);

setCE(1);

//messege(mes_werror);

return ;   //fail

}

 

}

}

skip1:

setOE(1);

setCE(1);

}

int blockWrite(unsigned char *data,short dsize,short addr)

{

short i;

unsigned char d;

setOE(1);

setWE(1);

setCE(0);

for (i=0;i<dsize;i++){

setAddr(0x0555);

setData(0xAA);

WE_pulse();

setAddr(0x0AAA);

setData(0x55);

WE_pulse();

setAddr(0x0555);

setData(0xA0);

WE_pulse();

setAddr(addr+i);

setData(data[i]);

WE_pulse();

 

//書き込み完了待ち(D7の反転を検出する)

setOE(0);

d=data[i] & 0x80;

while (1) {

if ( (readData()& 0x80) ==d ){

break;

}

if (readData() & 0x20){

if ( (readData()& 0x80) ==d ){

break;

}else{

setOE(1);

setCE(1);

return 0;   //fail

}

 

}

}

setOE(1);

}

setCE(1);

return (1);   //success

}

unsigned char rom_read(unsigned short addr)

{

setWE(1);

setCE(0);

setAddr(addr);

setOE(0);

return (readData());

}

void setOE(unsigned char x)

{

if (x){PORTC |= 4;DDRB=0xFF;}else{DDRB=0x00;PORTC &= 0xFB;}

}

void setWE(unsigned char x)

{

if (x){PORTC |= 2;}else{PORTC &= 0xFD;}

}

void setCE(unsigned char x)

{

if (x==0){PORTC |= 1;}else{PORTC &= 0xFE;}

}

void WE_pulse(void)

{

PORTC &= 0xFD;

PORTC |= 2;

}

void setAddr(unsigned short addr)

{

setOE(1);

PORTB = addr & 0xff;

PORTC &= 0xF7;

PORTC |= 8;

PORTB = addr >>8;

PORTC &= 0xEF;

PORTC |= 0x10;

}

void setPage(unsigned char p)

{

PORTD = (PORTD & 0xE3) | (p<<2);

}

void busSelect(int bus)

{

if (bus==0){ //SCV

DDRC = (DDRC & 0xC0) | 0x38;

PORTC = (PORTC & 0xc0 ) | 0x3E;

DDRB=0;

}else{ //AVR

DDRC = (DDRC & 0xC0) | 0x3F;

PORTC = (PORTC & 0xc0 ) | 0x1F;

DDRB=0;

}

}

int eraseChip()

{

setOE(1);

setWE(1);

setCE(0);

 

setAddr(0x555);

setData(0xAA);

WE_pulse();

setAddr(0xAAA);

setData(0x55);

WE_pulse();

setAddr(0x555);

setData(0x80);

WE_pulse();

setAddr(0x555);

setData(0xAA);

WE_pulse();

setAddr(0xAAA);

setData(0x55);

WE_pulse();

setAddr(0x555);

setData(0x10);

WE_pulse();

/*

* [DQ7ポーリング]

* DQ7 == 0 チップ消去進行中

* DQ7 == 1 チップ消去完了

*/

setOE(0);

while ((readData() & 0x80) == 0)

; // @TODO タイムアウト処理

setOE(1);

 

setCE(1);

return 1;

}

void makeTable()

{

int i;

unsigned char v;

for (i=0;i<256;i++){

v=(i&128)?1:0;

v|=(i&64)?2:0;

v|=(i&32)?4:0;

v|=(i&16)?8:0;

v|=(i&8)?16:0;

v|=(i&4)?32:0;

v|=(i&2)?64:0;

v|=(i&1)?128:0;

rTable[i]=v;

}

}

void setData(unsigned char x)

{

PORTB=x;

}

unsigned char readData(void)

{

return(PINB);

}

void uart_setting(void)

{

unsigned char data = 0;  //受信したデータを格納

 

//送受信有効の場合、ポートD方向レジスタ(DDRD)のDDD1の値に拘らずRX/TXとして設定されます。

DDRD = 0b11111100;       //portD : 0,1:UART 2,3,4:BANK 5:LED 6,7:NC

DDRB = 0b00000000;      //portB : 0-7 DATA

DDRC = 0b00111111;      //portC :0 ROM_CS 1:WE 2:OR 3:ALCK 4:AHCK 5:574OE 6:ISP_RESET

PORTD = 0b00000000;

PORTC = 0b00111110;

 

UBRR0 = 51;   //ボーレート9600 @8MHz

 

UCSR0A = 0b00000000;    //受信すると10000000になる

//送信有効になると00100000になる

 

UCSR0B = 0b00011000;    //送受信有効

UCSR0C = 0b00000110;    //データ8bit

//非同期,パリティなし

//Stop 1bit

 

//sei(); /* enable grobal interrupt */

return;

}

ISR (USART_RX_vect)

{

unsigned char data = 0;

data = UDR0;

if (sComCount<8){

combuf[sComCount++]=data;

combuf[sComCount]=0;

}

}

void messege(const char *mes)

{

//mes must be flash

char data=1;

while (data){

data=pgm_read_byte(mes++);

sendchar(data);

if (data==10){

sendchar(13);

}

}

 

}

void print(const char *mes)

{

//mes must be flash

char data=1;

while (data){

data=*mes++;

if (data!=0){

sendchar(data);

}

}

 

}

void BIGLETTER(char *strp)

{

char data=1;

int cc=0;

while (data) {

data=strp[cc];

if ((data>='a')&&(data<='z')){

strp[cc]=strp[cc]-0x20;

}

cc++;

}

}

void sendchar(char data)

{

while( !(UCSR0A & 0b00100000) );

UDR0 = data;

}

void sendreturn(void)

{

sendchar(13);

sendchar(10);

}

int hextoi(void)

{

int res=0;

char data;

data=hextois(combuf[sComCount]);

if (data==-1) return(-1);

res=data;

while (data!=-1) {

sComCount++;

data=hextois(combuf[sComCount]);

if (data>=0) {res= (res<<4) | data;}

}

return(res);

}

void printByte(unsigned char data)

{

printNibble(data >>4 );

printNibble(data & 0x0f);

}

void printShort(unsigned int data)

{

printNibble(data >>12 );

printNibble((data>>8) & 0x0f);

printNibble((data>>4) & 0x0f);

printNibble(data & 0x0f);

}

void printNibble(char data)

{

if (data < 10) {

sendchar(data+'0');

}else{

sendchar(data-10+'A');

}

}

int hextois(char data)

{

int res=-1;

if ((data>='0')&&(data<='9')){res=data-'0';}

if ((data>='a')&&(data<='f')){res=data-'a'+10;}

if ((data>='A')&&(data<='F')){res=data-'A'+10;}

return(res);

}

short getchar(void)

{

short data;

if (UCSR0A & 0b10000000) {

data=(short)UDR0;

}else{

data=NOCHAR;

}

return(data);

}

void get_command()

{

int ccount=0;

short data=0;

while(data!=13){

data=getchar();

switch (data) {

case -1:

break;

case 13:

sendchar(13);

sendchar(10);

break;

case 8:

if (ccount != 0){

combuf[ccount-1]=0;

ccount--;

sendchar(data);

}

break;

 

default:

if (ccount < BUFLENGTH ){

if (data>31){

combuf[ccount++]=data;

combuf[ccount]=0;

sendchar(data);

}

}

break;

}

}

}

int uart_test(void)

{

unsigned char data = 0;  //受信したデータを格納

 

//送受信有効の場合、ポートD方向レジスタ(DDRD)のDDD1の値に拘らずRX/TXとして設定されます。

DDRD = 0b11111100;       //portD : 0,1pin以外出力

PORTD = 0b00000000;

 

UBRR0 = 51;   //ボーレート9600 @8MHz

 

UCSR0A = 0b00000000;    //受信すると10000000になる

//送信有効になると00100000になる

 

UCSR0B = 0b00011000;    //送受信有効

UCSR0C = 0b00000110;    //データ8bit

//非同期,パリティなし

//Stop 1bit

 

while(1){

//受信するまで待つ

while( !(UCSR0A & 0b10000000) );  //0ならループ

data = UDR0;  //受信したデータを格納

 

//受信できたかを確認するために受信データを返す

//送信できるまで待つ

while( !(UCSR0A & 0b00100000) );  //0ならループ

UDR0 = data;  //受信したデータを送信

}

 

return 0;

}