同人誌即売会で頒布した「シンプル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;
}