Z80

パチパチマイコン用 bootloader

2011年12月6日

パチパチ式のコンピューターでは通常、電源を入れた後にトグルスイッチを用いて小さなプログラムを入力し、このプログラムを用いて紙テープインターフェースなどから大規模なプログラムを読み込む。現在製作中のパチパチマイコンも、この方式に従っている。

しかしながら、紙テープからの読み込みプログラムは非常に小規模ですむが、カセットテープインターフェースからの読み込みプログラムは少し規模が大きくなる。これを毎回打ち込むのは大変だ。

そこで、そういった小規模のプログラムの入力を、PICマイコンに行わせることにした。少しルール違反のような気もしたが、トグルスイッチでの入力を肩代わりするだけと考えれば、これもよいだろうと言うことで。

2011-12-06-Image.png

メモリー空間の最初の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();
}

コメント

コメントはありません

コメント送信