TOPへ戻る

メニュー

■動画
■回路図・部品表
■解説
■ソースファイル
■ソースファイルのダウンロード
■今後について
■参考URL

20091004 AVRに長門さんがいらしたようです



回路図・部品表

■回路図
←クリックすると拡大します。

■部品リスト
部品番号 部品名 単価 個数 仕入先
CN1 2.1mm標準DCジャック(基板取付用) MJ-179P 内径2.1mm 外形 5.5mm 40円 1個 秋月電子通商
CN2 ピンヘッダ(オス) 40P(1×40) 50円 1個 秋月電子通商
U1 ATMEGA168-20PU 525円 1個 マルツパーツ館
U2 GDM12864H 2480円 1個 ストロベリー・リナックス
U3 多出力クリスタルオシレータ EXO3(20MHz) 250円 1個 秋月電子通商
R1 金属皮膜抵抗器 1/4w 4.3kΩ 1個  
C1,C2 パスコン 0.1uF 1個  
VR1 可変抵抗器 10kΩ 1個  
PB1 ブレッドボード 1個 秋月電子通商

←クリックすると拡大し

解説

このページの下のほうに載せてありますが、ニコニコ動画でPICに長門さんがいらしたようです
を見て、AVR版を作ってみました。
作るにはハイスペックでなければと思って、CPUはATmega168-20MHz、液晶はGDM12864にしました。
忠実に再現するために漢字fontを載せようと考えました。
8x8の漢字フォントは恵梨沙フォントを使い、ビットマップフォントを組み込みで使おう!さんの、データを使用しています。
Size after:
AVR Memory Usage
----------------
Device: atmega168

Program:   55726 bytes (340.1% Full)
(.text + .data + .bootloader)

Data:      55550 bytes (5424.8% Full)
(.data + .bss + .noinit)
大きすぎて、絶対 ATmega168 内に入りませんので、使用するフォントだけ抜き出す方式に変更。
一文字一文字手動で拾うのは大変なので、VBAでやっつけプログラムを作成。
←クリックすると拡大します
Option Explicit

Sub 文字列toFontData()
    Dim start_ad As Long
    Dim end_ad As Long
    Dim strcode As String
    Dim foundcell As Integer
    
    Dim i As Integer
    Dim j As Integer
    Dim in_s As String
    Dim foo As String

    For i = 2 To 30
        Cells(i, 1) = ""
    Next i

    in_s = Cells(1, 1)                          ' 変換する文を読み込む
    
    For i = 1 To Len(in_s)
        foo = Mid(in_s, i, 1)                   ' 1文字取り出し
        strcode = CLng("&h" & Hex(Asc(foo)))    'JISコードに変換し数値化

        For j = 0 To 87
            foo = Sheet1.Cells(7169 + j, 2)
            start_ad = CLng("&h" & Mid(foo, 4, 4))
            end_ad = CLng("&h" & Mid(foo, 11, 4))
            If start_ad <= strcode And end_ad >= strcode Then
                foo = Mid(foo, 24, 14)
                Exit For
            End If
        Next j

        foundcell = Sheet1.Cells.Find(What:=foo).Row
        foo = Sheet1.Cells(foundcell + (strcode - start_ad + 2), 2)
        Cells(i + 1, 1) = Mid(foo, 2, Len(foo) - 3)

    Next i

End Sub
←クリックすると拡大します
こんな感じにA1セルに文字を入れて、マクロを実行すうと、sheet1からフォントデータを
拾ってきてくれます。

ソースファイル

■ソースファイル
#include "font.h" 
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
 
#define LCD_E   0x08    // モデル、ピン配置によって変更する。
#define LCD_DI  0x04
#define LCD_CS1 0x02
#define LCD_CS2 0x01
#define LCD_CONT PORTC
#define LCD_DATA PORTD

unsigned char cXpos,cYpos,cT;
unsigned int FontPosData;
int Flag; 

void commut_lcd(void);
void erase_lcd(char line);
void print_lcd(char xp, char yp, char *chaine);
void lcd(char cVar); 

void lcd_wait( int m )
{
//  _delay_ms(m); 引数を渡しちゃだめ。wiki参照
    while(m--) _delay_ms(1);
}

void lcd(char cVar)   
{
    LCD_DATA = cVar;
    _delay_us(140+10);              // Tasu 140ns(Min)

    LCD_CONT |= LCD_E;
    _delay_us(450+10);              // Twh 450ns(Min)

    LCD_CONT &= ~LCD_E;
}

/*-------------------------------------------------------------
    cX(dot) cY(行)
--------------------------------------------------------------*/
void print_lcd(char cX, char cY, char *chaine)
{
    cXpos=cX-1;
    cYpos=cY-1;
    Flag=0;
    commut_lcd(); 

    while(*chaine != 0){
        FontPosData=(int)((*chaine++)-32)*5;        // 表示する文字の格納位置を計算
        for( cT = 0 ; cT <= 5 ; cT++ ){             // 1文字表示処理
            if(cXpos>=64 && Flag==0){
                commut_lcd();
                Flag=1;
            }
            if(cT==5)
                lcd(0);
            else {
                lcd(pgm_read_byte(&tab_font[FontPosData+cT]));
            }
                cXpos++;
        }
    lcd_wait(150);//150ms
    }
}

/*-------------------------------------------------------------
    cX(dot) cY(行)
--------------------------------------------------------------*/
void print_lcd_elisa(char cX, char cY,char *yuki)
{
    int i=0;
    cXpos=cX-1;
    cYpos=cY-1;
    Flag=0;
    commut_lcd(); 

    for(;;){
        FontPosData=i*8;        // 表示する文字の格納位置を計算
        if(pgm_read_byte(&yuki[FontPosData])==0xff && pgm_read_byte(&yuki[FontPosData+1])==0xff )
            break;
        for( cT = 0 ; cT <= 8 ; cT++ ){             // 1文字表示処理
            if(cXpos>=64 && Flag==0){
                commut_lcd();
                Flag=1;
            }
            if(cT==8)
                lcd(0);
            else {
                lcd(pgm_read_byte(&yuki[FontPosData+cT]));
            }
                cXpos++;
        }
    lcd_wait(150);//150ms
    i++;
    }
}



void commut_lcd(void) 
{
    if(cXpos >= 64){                    // 右側のLCD
        LCD_CONT |= LCD_CS1;
        LCD_CONT &= ~LCD_CS2;
    }else{                              // 左側のLCD
        LCD_CONT |= LCD_CS2;
        LCD_CONT &= ~LCD_CS1;
    }

    LCD_CONT &= ~LCD_DI;                // instruction code

    lcd(0xB8 + cYpos);                  // Set Address(X address) page
    if(cXpos >=64) cXpos -=64;
    lcd(0x40 + cXpos);                  // Set Address(y address)
    LCD_CONT |= LCD_DI;                 // data code
    }

void erase_lcd(char line)  
{
    char cy;

    LCD_CONT |= LCD_CS1;                // 左エリア有効
    LCD_CONT |= LCD_CS2;                // 右エリア有効
    LCD_CONT &= ~LCD_DI;                // instruction code

    lcd(0xC0);                          // Set Address(X address) Page0

    if(line){
        lcd(0x40);                      // Set Address(Y address)
        lcd(0xB8 + (line-1));           // page++ Set Address(X address)
        LCD_CONT |= LCD_DI;             // data code

        for( cy = 0 ; cy <= 63 ; cy++ )
            lcd(0); 
    }
    else {
        for( cT = 0 ; cT <= 7 ; cT++ ){
            LCD_CONT &= ~LCD_DI;        // instruction code
            lcd(0x40);                  // Set Address(Y address)
            lcd(0xB8 +cT);              // page++ Set Address(X address)
            LCD_CONT |= LCD_DI;
            for( cy = 0 ; cy <= 63 ; cy++ )
                lcd(0);
        }
    }
}

void init_lcd(void)
{
    PORTD=0x00;         // LCD DATA BUS 全ピン 0 出力
    DDRD = (1<<PB7)| (1<<PB6)|(1<<PB5)|(1<<PB4)|(1<<PB3)|(1<<PB2)|(1<<PB1)|(1<<PB0);    // PortB 全ピン出力モード

    PORTC = 0x00;   // LCD CONTROL SIG 全ピン 0 出力
    DDRC = (1<<PD3)|(1<<PD2)|(1<<PD1)|(1<<PD0); // PortC PC0-PD3
    //  DDRC = (1<<PD6)|(1<<PD5)|(1<<PD4)|(1<<PD3)|(1<<PD2); // PortD PD2-PD6 (※SIO用にPD0,PD1は空き)

    for( cT = 0 ; cT <= 1 ; cT++ ){
        LCD_CONT &= ~LCD_DI;            // instruction code

        if(cT){
            LCD_CONT &= ~LCD_CS1;       // 左エリア無効
            LCD_CONT |= LCD_CS2;        // 右エリア有効
        }
        else{
            LCD_CONT |= LCD_CS1;        // 左エリア有効
            LCD_CONT &= ~LCD_CS2;       // 右エリア無効
        }

        lcd(0x3F);                      // lcd on
        lcd(0xC0);                      // Set Display Start Line
    }

    erase_lcd(0);

}

void cursor_blnk(int x, int y, int n)
{
    int i;
    for(i=0;i<n;i++){
        print_lcd(x,y,"_");
        lcd_wait(500);      //500ms
        print_lcd(x,y," ");
        lcd_wait(500);      //500ms
    }
}


void main(void)
{
//#ifdef debug
    init_lcd();

    cursor_blnk(1,1,5);

    print_lcd(1,1,"YUKI.N>");
    print_lcd_elisa(6*7,1,&yuki1);  // みえてる?
    cursor_blnk(6*7+9*5,1,2);

    print_lcd_elisa(1,2,&yuki2);    // ああ
    cursor_blnk(9*2,2,1);

    print_lcd(1,3,"YUKI.N>");
    print_lcd_elisa(6*7,3,&yuki3);  // そっちの時空間とは
//  print_lcd_elisa(6*7,4,&yuki4);  // まだ完全には連結を絶たれていない。
    print_lcd_elisa(6*7,4,&yuki4a);// まだ完全には連結を
    print_lcd_elisa(6*7,4,&yuki4b);// 絶たれていない。 
    lcd_wait(500);      //500ms
    print_lcd_elisa(6*7,5,&yuki5);  // でも時間の問題。
    print_lcd_elisa(6*7,6,&yuki6);  // そうなれば最後。
    cursor_blnk(6*7+9*8,6,5);

//  print_lcd_elisa(  1,7,&yuki7);  // どうすりゃいい?
    print_lcd_elisa(  1,7,&yuki7a);// d
    print_lcd_elisa(  1,7,&yuki7b);// ど
    print_lcd_elisa(1*9,7,&yuki7c);// う
    print_lcd_elisa(2*9,7,&yuki7d);// s
    print_lcd_elisa(2*9,7,&yuki7e);// す
    print_lcd_elisa(3*9,7,&yuki7f);// r
    print_lcd_elisa(3*9,7,&yuki7g);// y
    print_lcd_elisa(3*9,7,&yuki7h);// り
    print_lcd_elisa(4*9,7,&yuki7i);// ゃ
    print_lcd_elisa(5*9,7,&yuki7j);// い
    print_lcd_elisa(6*9,7,&yuki7j);// い
    print_lcd_elisa(7*9,7,&yuki7k);// ?

    cursor_blnk(9*8,7,2);

    print_lcd(1,8,"YUKI.N>");
    print_lcd_elisa(6*7,8,&yuki8);  // どうにもならない。
    cursor_blnk(6*7+9*9,8,5);

//#endif
//#ifdef debug

    init_lcd();

//  print_lcd_elisa(6*7,1,&yuki9);      // 情報統合思念体は失望している。
    print_lcd_elisa(6*7,1,&yuki9a); // 情報統合思念体は失
    print_lcd_elisa(6*7,1,&yuki9b); // 望している。   

    lcd_wait(500);      //500ms
//  print_lcd_elisa(6*7,2,&yuki10); // これで進化の可能性は失われた。
    print_lcd_elisa(6*7,2,&yuki10a);    // これで進化の可能性
    print_lcd_elisa(6*7,2,&yuki10b);    // は失われた。   

    cursor_blnk(6*7+8*6,2,5);
    print_lcd(1,3,"YUKI.N>");
    print_lcd_elisa(6*7,3,&yuki11); // 涼宮ハルヒは
    print_lcd_elisa(6*7,4,&yuki12); // 何もない所から
    print_lcd_elisa(6*7,5,&yuki13); // 情報を生み出す力を
    print_lcd_elisa(6*7,6,&yuki14); // 持っていた。
//  print_lcd_elisa(6*7,7,&yuki15); // それは情報統合思念体にも
    print_lcd_elisa(6*7,7,&yuki15a);    // それは情報統合思念
    print_lcd_elisa(6*7,7,&yuki15b);    // 体にも
    print_lcd_elisa(6*7,8,&yuki16); // ない力。
    cursor_blnk(6*7+8*4,8,2);

//#endif
//#ifdef debug

    init_lcd();

//  print_lcd_elisa(6*8,1,&yuki17); // この情報創造能力を解析すれば
    print_lcd_elisa(6*8,1,&yuki17a);    // この情報創造能力を
    print_lcd_elisa(6*8,1,&yuki17b);    // 解析すれば    
    lcd_wait(500);      //500ms
    print_lcd_elisa(6*8,2,&yuki18); // 自律進化への糸口が
//  print_lcd_elisa(6*8,3,&yuki19); // つかめるかもしれないと考えた。
    print_lcd_elisa(6*8,3,&yuki19a);    // つかめるかもしれな
    print_lcd_elisa(6*8,3,&yuki19b);    // いと考えた。   

    cursor_blnk(1,4,2);

//#endif
//#ifdef debug

    init_lcd();

    print_lcd(1,1,"YUKI.N>");
    print_lcd_elisa(6*7,1,&yuki20); // あなたに賭ける。
    cursor_blnk(6*7+8*9,1,2);
    print_lcd_elisa(1,2,&yuki21);       // 何をだよ
    print_lcd(1,3,"YUKI.N>");
//  print_lcd_elisa(6*7,3,&yuki22); // もう一度こちらへ回帰することを
    print_lcd_elisa(6*7,3,&yuki22a);    // もう一度こちらへ回
    print_lcd_elisa(6*7,3,&yuki22b);    // 帰することを   

    print_lcd_elisa(6*7,4,&yuki23); // 我々は望んでいる。
    lcd_wait(500);      //500ms
//  print_lcd_elisa(6*7,5,&yuki24); // 涼宮ハルヒは重要な観察対象。
    print_lcd_elisa(6*7,5,&yuki24a);    // 涼宮ハルヒは重要な
    print_lcd_elisa(6*7,5,&yuki24b);    // 観察対象。    

    lcd_wait(500);      //500ms
    print_lcd_elisa(6*7,6,&yuki25); // わたしという個体も
    lcd_wait(500);      //500ms
//  print_lcd_elisa(6*7,7,&yuki26); // あなたには戻ってきて欲しいと感じている。
    print_lcd_elisa(6*7,7,&yuki26a);    // あなたには戻ってき
    print_lcd_elisa(6*7,7,&yuki26b);    // て欲しいと感じてい
    print_lcd_elisa(6*7,7,&yuki26c);    // る。
    cursor_blnk(6*7+8*2,7,2);

//#endif
//#ifdef debug

    init_lcd();

    print_lcd(1,1,"YUKI.N>");
    cursor_blnk(6*7,1,2);

//  print_lcd_elisa(6*7,1,&yuki27);     // また図書館に
    print_lcd_elisa(6*7,1,&yuki27a);        // また
    lcd_wait(500);      //500ms
    print_lcd_elisa(6*7+8*2+3,1,&yuki27b);  // 図
    print_lcd_elisa(6*7+8*3+3,1,&yuki27c);  // 書
    print_lcd_elisa(6*7+8*4+3,1,&yuki27d);  // 館
    print_lcd_elisa(6*7+8*5+3,1,&yuki27e);  // に

    cursor_blnk(6*7+8*7,1,2);

    init_lcd();

    print_lcd(1,1,"YUKI.N>");
    print_lcd(6*7,1," sleeping beau");
    print_lcd(6*7,2,"ty");
    cursor_blnk(6*9,2,2);
//#endif

    LCD_CONT &= ~LCD_CS1;
    LCD_CONT &= ~LCD_CS2;

    while(1);

}
ソースファイルのダウンロード

ソースファイルのダウンロード
EXCELのマクロファイルのダウンロード

参考URL



恵梨沙フォントHomePage

ビットマップフォントを組み込みで使おう!

Disconnected Place 切り離された空間



2009/10/06 1版 とりあえずうp