同人誌即売会で頒布した「シンプルROMリーダー」のファームウェア・回路図・マニュアルをダウンロードできます。
「プログラム・開発」カテゴリーアーカイブ
スパカセ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; }