パチパチマイコン用 bootloader
2011年12月6日
パチパチ式のコンピューターでは通常、電源を入れた後にトグルスイッチを用いて小さなプログラムを入力し、このプログラムを用いて紙テープインターフェースなどから大規模なプログラムを読み込む。現在製作中のパチパチマイコンも、この方式に従っている。
しかしながら、紙テープからの読み込みプログラムは非常に小規模ですむが、カセットテープインターフェースからの読み込みプログラムは少し規模が大きくなる。これを毎回打ち込むのは大変だ。
そこで、そういった小規模のプログラムの入力を、PICマイコンに行わせることにした。少しルール違反のような気もしたが、トグルスイッチでの入力を肩代わりするだけと考えれば、これもよいだろうと言うことで。

メモリー空間の最初の256バイト分が、PICのEEPROMから読み込まれる仕組み。
PICのVDDラインにはスイッチが付いていて、これを切ることでリセットを行う。330 Ωの抵抗は、コンデンサーの残りを消費するためのもの。また、VDDライン以外のところからの+5 Vの電圧でも、消費電力を落としたPICはスリープ状態を保持するようで、この抵抗を入れないとちゃんとリセットが出来なかった。
ジャンパーの設定で、書き込みと読み出しを区別する。PICのプログラムでは、まず、アドレス0x00と0x01から読み出しのトライを行う。LD SP,xx00に相当する0x31と0x00が順次読み出せれば、/RDにジャンパーが設定されていると判断し、RAMから読み込んだ内容を内蔵のEEPROMに保存。LD SP,xx00が読み出しできなければ、/WRにジャンパーが設定されていると判断し、EEPROMの内容をRAMに書き込む。
なお、これらの動作は、/BUSACKがLになっているときにのみ行われる。
しかしながら、紙テープからの読み込みプログラムは非常に小規模ですむが、カセットテープインターフェースからの読み込みプログラムは少し規模が大きくなる。これを毎回打ち込むのは大変だ。
そこで、そういった小規模のプログラムの入力を、PICマイコンに行わせることにした。少しルール違反のような気もしたが、トグルスイッチでの入力を肩代わりするだけと考えれば、これもよいだろうと言うことで。

メモリー空間の最初の256バイト分が、PICのEEPROMから読み込まれる仕組み。
PICのVDDラインにはスイッチが付いていて、これを切ることでリセットを行う。330 Ωの抵抗は、コンデンサーの残りを消費するためのもの。また、VDDライン以外のところからの+5 Vの電圧でも、消費電力を落としたPICはスリープ状態を保持するようで、この抵抗を入れないとちゃんとリセットが出来なかった。
ジャンパーの設定で、書き込みと読み出しを区別する。PICのプログラムでは、まず、アドレス0x00と0x01から読み出しのトライを行う。LD SP,xx00に相当する0x31と0x00が順次読み出せれば、/RDにジャンパーが設定されていると判断し、RAMから読み込んだ内容を内蔵のEEPROMに保存。LD SP,xx00が読み出しできなければ、/WRにジャンパーが設定されていると判断し、EEPROMの内容をRAMに書き込む。
なお、これらの動作は、/BUSACKがLになっているときにのみ行われる。
#include <pic.h>
/*
// Oscillator
#define EXTCLK 0x3FFF // External RC Clockout
#define EXTIO 0x3FFE // External RC No Clock
#define INTCLK 0x3FFD // Internal RC Clockout
#define INTIO 0x3FFC // Internal RC No Clock
#define EC 0x3FFB // EC
#define HS 0x3FFA // HS
#define XT 0x3FF9 // XT
#define LP 0x3FF8 // LP
// Watchdog Timer
#define WDTEN 0x3FFF // On
#define WDTDIS 0x3FF7 // Off
// Power Up Timer
#define PWRTDIS 0x3FFF // Off
#define PWRTEN 0x3FEF // On
// Master Clear Enable
#define MCLREN 0x3FFF // MCLR function is enabled
#define MCLRDIS 0x3FDF // MCLR functions as IO
// Code Protect
#define UNPROTECT 0x3FFF // Code is not protected
#define CP 0x3FBF // Code is protected
#define PROTECT CP //alternate
// Data EE Read Protect
#define UNPROTECT 0x3FFF // Do not read protect EEPROM data
#define CPD 0x3F7F // Read protect EEPROM data
// Brown Out Detect
#define BORDIS 0x3CFF // BOD and SBOREN disabled
#define SWBOREN 0x3DFF // SBOREN controls BOR function (Software control)
#define BORXSLP 0x3EFF // BOD enabled in run, disabled in sleep, SBOREN disabled
#define BOREN 0x3FFF // BOD Enabled, SBOREN Disabled
// Internal External Switch Over Mode
#define IESOEN 0x3FFF // Enabled
#define IESODIS 0x3BFF // Disabled
// Monitor Clock Fail-safe
#define FCMEN 0x3FFF // Enabled
#define FCMDIS 0x37FF // Disabled
*/
__CONFIG(INTIO & WDTDIS & PWRTDIS & MCLRDIS & UNPROTECT & BORDIS & IESODIS & FCMDIS);
//───────────────────────────────────
// Read data
//───────────────────────────────────
unsigned char E2promRead( unsigned char adr )
{
EEADR = adr;
RD = 1; // Set read bit
return( EEDATA ); // Return read data
}
//───────────────────────────────────
// Write data
//───────────────────────────────────
void E2promWrite( unsigned char adr, unsigned char data )
{
EEADR = adr;
EEDATA = data;
WREN = 1; // Set write enable bit
EECON2 = 0x55;
EECON2 = 0xaa;
WR = 1; // Set programming bit
while( EEIF == 0 ) // Wait till write operation complete
{
NOP();
}
EEIF = 0; // Clear EEPROM write complete bit
WREN = 0; // Clear write enable bit
}
/*
* RC0-RC7: conntected to D0-D7
* RA0-RA1: conntected to A0-A1
* RA4-RA5: conntected to A2-A3
* RB4-RB7: conntected to A4-A7
* RA2: WR/RD (active low)
* RA3: BUSREQ (active low)
*/
void init(){
// Disable all interrupt events
INTCON=0;
// RA: input, RB:input, RC: input
TRISA=0xff;
TRISB=0xff;
TRISC=0xff;
// Non-analog mode
ANSEL=0x00;
ANSELH=0x00;
// CLK=31 kHz
OSCCON=0x0a;
// Pull-up disabled
RABPU=1;
}
unsigned char readRAM(unsigned char addr){
unsigned char data;
if (RA3) return 0xff;
TRISA=0x08; // output except for RA3
TRISB=0x00; // output
TRISC=0xff; // input
PORTB=addr & 0xf0;
PORTA=(addr & 0x03) | ((addr & 0x0c)*4) | 0x04;
RA2=0;
data=PORTC;
RA2=1;
TRISA=0xff; // input
TRISB=0xff; // input
return data;
}
void writeRAM(unsigned char addr, unsigned char data){
if (RA3) return;
RA2=1;
TRISA=0x08; // output except for RA3
TRISB=0x00; // output
TRISC=0x00; // output
PORTB=addr & 0xf0;
PORTA=(addr & 0x03) | ((addr & 0x0c)*4) | 0x04;
RA2=0;
PORTC=data;
RA2=1;
TRISA=0xff; // input
TRISB=0xff; // input
TRISC=0xff; // input
}
void main(){
unsigned char i,data;
init();
if (!RA3) {// BUSACK active low
// Wait for a second
for(i=0;i<255;i++);
// CLK=8 MHz
OSCCON=0x70;
// if first two bytes correspond to LD SP,xx00, it is now reading mode.
if (readRAM(0)==0x31 && readRAM(1)==0x00) {
// reading mode
i=0;
do {
data=readRAM(i);
TRISC=0x00; // output
PORTC=1<<(i&7);
E2promWrite(i,data);
TRISC=0xff; // input
} while ((++i)!=0 && !RA3);
} else if (readRAM(0)==readRAM(1)) {
// writing mode
writeRAM(0,0x31); // LD SP
writeRAM(1,0x00); // ,xx00
i=2;
do {
writeRAM(i,E2promRead(i));
} while ((++i)!=0 && !RA3);
}
}
// RA: input, RB:input, RC: input
TRISA=0xff;
TRISB=0xff;
TRISC=0xff;
// CLK=31 kHz
OSCCON=0x0a;
SLEEP();
}