Posts Tagged with "Design"

既に発行済みのブログであっても適宜修正・追加することがあります。
We may make changes and additions to blogs already published.
posted by sakurai on August 8, 2026 #1102

Geminiに設計してもらったプログラムをClaudeに修正してもらったものを以下に示します。

/* ============================================================
 *  NY_night  --  PIC12F1501 LED driver
 *  rev.3 : SMD / PCBA board (AO3400A output stage) + sleep
 *
 *  RA2 = PWM1 -> R2 -> T2 gate -> L_N   (Left channel)
 *  RA4 = PWM3 -> R1 -> T1 gate -> R_N   (Right channel)
 *  RA5 = mode button (SW1, to GND, internal pull-up)
 *  RA3 = unused input, brought out to JP1 pin 1 (MCLR/VPP)
 *
 *  Modes: 1 alternating fade -> 2 steady -> 3 blink -> SLEEP -> 1 ...
 *  In sleep the core is stopped; a button press wakes it via IOC.
 * ============================================================ */

#pragma config FOSC     = INTOSC   /* internal oscillator                 */
#pragma config WDTE     = OFF      /* watchdog off                        */
#pragma config PWRTE    = ON       /* power-up timer on                   */
#pragma config MCLRE    = OFF      /* pin 4 is RA3, not MCLR              */
#pragma config CP       = OFF      /* code protect off                    */
#pragma config BOREN    = NSLEEP   /* BOR active when running, off asleep */
#pragma config CLKOUTEN = OFF      /* no clock output                     */
#pragma config BORV     = LO       /* low BOR threshold (battery)         */
#pragma config LPBOR    = OFF      /* low-power BOR off                   */
#pragma config LVP      = OFF      /* HV programming via JP1              */

#include 
#include 

#define _XTAL_FREQ 4000000

/* ---- timing, all expressed in 10 ms ticks ---- */
#define TICK_MS         10
#define FADE_TICKS       4     /*  40 ms per fade step   */
#define BLINK_TICKS     30     /* 300 ms per blink phase */
#define DEBOUNCE_TICKS   3     /*  30 ms settle time     */

#define FADE_STEP        5
#define DUTY_MAX       250
#define DUTY_MIN         5

#define PWM_L  PWM1DCH         /* RA2, pin 5 */
#define PWM_R  PWM3DCH         /* RA4, pin 3 */

#define SW_PRESSED  (RA5 == 0)

/* ------------------------------------------------------------
 *  Output stage on / off
 *  With the PWM modules disabled the pins revert to port
 *  control; LATA = 0 holds both gates low, and R3/R4 back
 *  that up so the MOSFETs cannot float on.
 * ---------------------------------------------------------- */
static void outputs_off(void)
{
    PWM_L   = 0;
    PWM_R   = 0;
    PWM1CON = 0x00;
    PWM3CON = 0x00;
    T2CONbits.TMR2ON = 0;
    LATA    = 0x00;
}

static void outputs_on(void)
{
    LATA    = 0x00;
    PWM_L   = 0;
    PWM_R   = 0;
    PR2     = 255;
    T2CONbits.TMR2ON = 1;
    PWM1CON = 0xC0;
    PWM3CON = 0xC0;
}

/* ------------------------------------------------------------
 *  Sleep until the button is pressed.
 *  GIE stays 0, so the core resumes at the instruction after
 *  SLEEP() instead of vectoring to an ISR -- no ISR needed.
 * ---------------------------------------------------------- */
static void sleep_until_button(void)
{
    outputs_off();

    IOCAF = 0x00;                  /* clear any stale edge flag  */
    IOCANbits.IOCAN5 = 1;          /* wake on RA5 falling edge   */
    INTCONbits.IOCIE = 1;
    INTCONbits.GIE   = 0;

    SLEEP();
    NOP();

    IOCANbits.IOCAN5 = 0;
    INTCONbits.IOCIE = 0;
    IOCAF = 0x00;

    outputs_on();
}

int main(void)
{
    /* ---------------- initialisation ---------------- */
    OSCCON = 0x6A;             /* 4 MHz internal                        */
    ANSELA = 0x00;             /* all pins digital                      */
    LATA   = 0x00;             /* outputs low before they are enabled   */
    TRISA  = 0b00101000;       /* RA5 = button in, RA3 = input only     */
    WPUA   = 0b00101000;       /* pull up RA5 AND RA3                   */
    OPTION_REGbits.nWPUEN = 0; /* enable weak pull-ups globally         */

    T2CON = 0x04;              /* Timer2 on, prescale 1:1               */
    outputs_on();              /* PWM period 3.9 kHz, both channels 0   */

    /* ---------------- state ---------------- */
    uint8_t mode     = 1;      /* 0:sleep  1:fade  2:steady  3:blink */
    uint8_t duty     = 0;
    int8_t  step     = FADE_STEP;

    uint8_t fade_t   = 0;
    uint8_t blink_t  = 0;
    uint8_t blink_on = 1;

    uint8_t sw_raw   = 0;      /* 1 = pressed */
    uint8_t sw_prev  = 0;
    uint8_t sw_state = 0;      /* debounced   */
    uint8_t dbnc     = DEBOUNCE_TICKS;

    while (1) {
        /* -------- button: non-blocking, acts on release -------- */
        sw_raw = SW_PRESSED ? 1 : 0;

        if (sw_raw != sw_prev) {
            dbnc = 0;                       /* level changed, restart timer */
        } else if (dbnc < DEBOUNCE_TICKS) {
            if (++dbnc == DEBOUNCE_TICKS) { /* level has settled            */
                if (sw_state == 1 && sw_raw == 0) {
                    mode = (uint8_t)((mode + 1) & 0x03);
                    duty     = 0;
                    step     = FADE_STEP;
                    fade_t   = 0;
                    blink_t  = 0;
                    blink_on = 1;
                }
                sw_state = sw_raw;
            }
        }
        sw_prev = sw_raw;

        /* -------- mode output -------- */
        switch (mode) {

        case 0:                             /* off -> sleep */
            sleep_until_button();

            /* Woken by a press. Go straight to mode 1 so that even a
             * very short tap responds, then swallow this press so the
             * release does not advance the mode a second time.        */
            mode = 1;
            while (SW_PRESSED) {
                __delay_ms(TICK_MS);
            }
            __delay_ms(30);                 /* release bounce */

            sw_raw = sw_prev = sw_state = 0;
            dbnc     = DEBOUNCE_TICKS;
            duty     = 0;
            step     = FADE_STEP;
            fade_t   = 0;
            blink_t  = 0;
            blink_on = 1;
            break;

        case 1:                             /* alternating fade */
            if (++fade_t >= FADE_TICKS) {
                fade_t = 0;
                if (step > 0) {
                    if (duty < DUTY_MAX) duty = (uint8_t)(duty + FADE_STEP);
                    else                 step = -FADE_STEP;
                } else {
                    if (duty > DUTY_MIN) duty = (uint8_t)(duty - FADE_STEP);
                    else                 step = FADE_STEP;
                }
            }
            PWM_L = duty;
            PWM_R = (uint8_t)(255 - duty);
            break;

        case 2:                             /* steady on */
            PWM_L = 255;
            PWM_R = 255;
            break;

        case 3:                             /* simultaneous blink */
            if (++blink_t >= BLINK_TICKS) {
                blink_t  = 0;
                blink_on ^= 1;
            }
            PWM_L = blink_on ? 255 : 0;
            PWM_R = blink_on ? 255 : 0;
            break;
        }

        __delay_ms(TICK_MS);
    }
}

左矢前のブログ 次のブログ右矢

posted by sakurai on August 7, 2026 #1101

Studio 500 3D Pop Up Wall Artの修理の続きです。前回のボードは基本的に動作したので、SMD化の改版を行います。改版はAIに手伝ってもらいます。まず製品の外観です。

図%%.1
図1101.1 Studio 500

次にAIに改版してもらった論理図です。プルダウン抵抗を100kΩにしたのは、駆動時の無駄電流を抑えるためです。RA2/RA4がHighのとき、470Ωを通してゲートに5Vがかかり、100kΩ経由でGNDへ50µAが流れ続けます。2チャンネルで100µA。単4電池駆動なので、ここは小さいほうが望ましいとのこと。

一方でリーク電流に対する引き込み能力としては100kΩで十分です。AO3400Aのゲートリークは最大100nA程度なので、100kΩなら10µVしか持ち上がりません。

なお470Ω(R1/R2)はプルダウンとは役割が別で、ゲート直列抵抗です。ゲート容量への突入電流を制限してPICのポートを保護し、スイッチングのリンギングを抑えます。100kΩとの分圧比は99.5%なので、オン時のゲート電圧はほぼVDDそのままです。

なおAIの部品配置は適当なので、部品間の配線は人手で接続しています。

図%%.2
図1101.2 点滅回路図

次にレイアウト図を示します。Claudeが言うには、背面GNDと全面GNDの間のVIAが少ないので、全面GNDパッド位置でVIAを打ち、背面の大きなGNDプレーンにコンタクトすべきとのことで、VIAを追加しました。前回不要だったのはDIP部品なので、前面がVDD, 背面がGNDときれいに分離できていたものが、今回はSMDなので、前面にVDDとGNDが混在するようになったためです。

面積はSMD化により旧ボードと比べて▲53%となっています。

図%%.3
図1101.3 点滅回路レイアウト図

左矢前のブログ 次のブログ右矢

GameFSMの改良 (25)

posted by sakurai on August 6, 2026 #1100

次に原作にもある「化石」という症状をインプリしてもらいました。

化石の動画

仕様: 化石の再現 隊列がシールド帯まで降下した状態で、左端での下降パス中に自弾が右端シールドに命中すると、これを個体命中と誤認する。シールド内の弾の位置に敵爆発音と敵爆発マークを発生させ、マーク消去時にシールドへ 16×8 の穴を開ける一方、実際に死ぬのは弾の真上とは別の列の最前列個体である。その個体の画像は消去されないまま画面に残り、以後は敵として撃てず、隊列だけが先へ進む。

発症条件の幾何定数 — 隊列の降下判定しきい値と、右端シールドの x 範囲。

`ifdef FOSSIL_BUG
`define FOSSIL_BUG_Y 176   // 原作バグ発症条件: 隊列がシールド上端(192)の1ピッチ以内                            
`define FOSSIL_BUG_X 182   // これ以右のシールド命中で発症(=右端シールド全体、x=182〜204)                       
`endif

爆発マークの描画・消去位置を保持する — 犠牲個体の座標から切り離すことで「マークと犠牲が別の場所」という原作バグの本質を表現可能にする。

`ifdef FOSSIL_BUG
   Reg#(UInt#(8)) expl_x <- mkRegU,   // インベーダ爆発マークの描画・消去位置                                   
                  expl_y <- mkRegU;   // (バグ再現時は個体位置とマーク位置が食い違う)                           
`endif

常キル時にマーク位置=個体位置を expl_x/expl_y へラッチする(挙動は従来と同一の中立改造)。

`ifdef FOSSIL_BUG
               eraseArea(
               expl_x,
               expl_y,
               16, 8);
`else
               eraseArea(
               inv_x[gx][gy],
               inv_y[gx][gy],
               16, 8);
`endif

マーク消去を個体座標ではなく expl_x/expl_y に対して行う(バグ時はシールド内を消して穴を開ける)。

`ifdef FOSSIL_BUG
      return (seq
         action
            alien_timer <= 1;
            expl_x <= inv_x[gx][gy];   // マーク位置=個体位置(通常キル)                                         
            expl_y <= inv_y[gx][gy];
         endaction
         copyArea(96, colorAtY(inv_y[gx][gy])*16+16,
                  inv_x[gx][gy], inv_y[gx][gy],
                  16, 8);
      endseq);
`else
      return (seq
         alien_timer <= 1;
         copyArea(96, colorAtY(inv_y[gx][gy])*16+16,
                  inv_x[gx][gy], inv_y[gx][gy],
                  16, 8);
      endseq);
`endif

発症4条件成立時のシールド命中を誤認キル化する本体 — マークと音は弾の位置、死ぬのは左端側の生存列の最前列、絵は残って化石になる。

`ifdef FOSSIL_BUG
               endseq else if (fbase && ymax >= `FOSSIL_BUG_Y
                               && inv_move == MoveLeftDown
                               && bullet_x >= `FOSSIL_BUG_X) seq
                  // ---- 原作バグの再現(希少条件版) ----                                                       
                  // 右→左で来て左端で下降中(=MoveLeftDown、隊列スキュー中)、                                  
                  // かつ隊列がシールド帯まで降りた状態で右端シールドを撃つと、                                 
                  // 原作の座標→個体逆算の破綻(左下原点からの列計算オーバー                                    
                  // フローが隣行へ回り込む)を模して、左端の生存個体が誤って                                    
                  // 殺される。マークと消去は弾の位置、犠牲の絵は左端に無傷で                                   
                  // 残り、隊列に取り残される(化石)。                                                           
                  fhit_alien <= False;
                  for (gx <= 0; gx < `InvCols; gx <= gx + 1) seq
                     if (inv_s[gx][inv_lead_y[gx]]) seq   // 左端の生存列を探す                                 
                        fhit_alien <= True;
                        break;
                     endseq
                  endseq
                  if (fhit_alien) seq
                     gy <= inv_lead_y[gx];
                     erasePlayerBullet(bullet_x, bullet_y);
                     inv_s[gx][gy] <= False;
                     inv_no <= inv_no - 1;
                     updateColumnFrontY();
                     playSound(SND_ALIEN_EXPLODE);
                     action                        // マークは弾の位置に描く                                    
                        alien_timer <= 1;
                        expl_x <= bullet_x - 8;
                        expl_y <= bullet_y;
                     endaction
                     copyArea(96, colorAtY(bullet_y)*16+16,
                              bullet_x - 8, bullet_y, 16, 8);
                     action
                        score <= score + inv_score[gy];
                        bscore <= bscore + inv_score[gy];
                     endaction
                  endseq else seq
                     erasePlayerBullet(bullet_x, bullet_y);   // 生存列なし: 通常のシールド命中                 
                     explodePlayerBullet(35, bullet_x, bullet_y);
                     bullet_timer <= 1;
                  endseq
`endif

左矢前のブログ 次のブログ右矢

GameFSMの改良 (24)

posted by sakurai on August 3, 2026 #1099

最近は推論能力が高いため、もっぱらClaude Fable 5を使用しています。さてCaludeに以下の仕様を実装してもらいました。

「自弾がインベーダに命中すると、爆発マークの表示期間(ALIEN_EXPL_TMAX tick)のあいだ隊列全体の移動を停止する。停止中も自機・自弾・敵弾・UFO・サウンドの処理は継続し、爆発マークの消去とともに、停止した個体から隊列の移動を再開する。」

これはオリジナル動作を観察して発見した仕様です。理由は不明ながら、爆発マーク表示中も隊列を動かすと、インベーダの動きにより爆発マークが欠ける場合があり、その干渉を防止するためと考えられます。

            for (noy <= 0; noy < `InvRows; noy <= noy + 1) seq
               // 爆発凍結中はカーソルを進めない(増分が no-op になる)
               for (nox <= 0; nox < `InvCols;
                    nox <= (alien_timer == 0) ? nox + 1 : nox) seq
                  if (inv_s[nox][noy] || alien_timer != 0) seq
                     if (alien_timer == 0)
                        updateAliens();
                     else
                        eraseAlienExplosion();
                     updatePlayer();
                     ...(以下、元のまま)...
                  endseq  // if inv
               endseq // for nox
            endseq // for noy

左矢前のブログ 次のブログ右矢

bitmap editorの開発

posted by sakurai on July 28, 2026 #1098

Claude Fable 5に仕様を渡して表記エディタを開発して貰いました。AI以前はこのような小さなヘルパーツールでも、一週間程度はかけて作成及びデバッグしたものでしたが、改良も含めて10分程でできてしまうことに感激です。もちろんコードは一行も書いてません。

ここで仕様の一部を示すと、ベースのcsvを読ませ、エディタによりaパターンとbパターンの作成を行うと、自動的にプレビューでパターン間の動作を確認できます。OKなら最下段のOKボタンを押すと、ベースのデータとスプライトのデータが合成され、ROMデータのcsvとなります。スプライトcsvは別にロードセーブ可能です。



左矢前のブログ 次のブログ右矢

posted by sakurai on March 29, 2026 #1070

Geminiに設計してもらったプログラムを以下に示します。

// --- コンフィギュレーション設定(マイコンの基本動作設定) ---
#pragma config FOSC = INTOSC    // 内蔵クロックを使用
#pragma config WDTE = OFF       // ウォッチドッグタイマーOFF
#pragma config PWRTE = ON       // パワーアップタイマーON
#pragma config MCLRE = OFF      // 4番ピンをリセットに使わずGPIO(RA3)として使う
#pragma config CP = OFF         // コードプロテクトOFF
#pragma config BOREN = ON       // 電圧低下で安全停止
#pragma config CLKOUTEN = OFF   // クロック出力OFF
#pragma config LVP = OFF        // 低電圧プログラミングOFF(ICSP動作を安定させる)

#include <xc.h>

// 動作クロックの定義(__delay_msの計算に必要)
#define _XTAL_FREQ 4000000 

void main(void) {
    // --- マイコンの初期化 ---
    OSCCON = 0x6A;          // 内部クロック4MHzに設定
    ANSELA = 0x00;          // 全ピンをデジタルモードに設定(スイッチ入力に必須)
    TRISA = 0b00100000;     // RA5(2番ピン)を入力、他を出力に設定
    WPUA = 0b00100000;      // RA5を内部プルアップ設定
    OPTION_REGbits.nWPUEN = 0; // 内部プルアップ機能を有効化

    // PWM(調光)の初期設定
    PWM1CON = 0xC0;         // PWM1(5番ピン/RA2)を有効化
    PWM3CON = 0xC0;         // PWM3(3番ピン/RA4)を有効化
    T2CON = 0x04;           // Timer2 ON, プリスケーラ1:1
    PR2 = 255;              // PWMの周期設定

    // 制御用変数の宣言
    unsigned char mode = 1;      // 0:消灯, 1:交互ゆらぎ, 2:全点灯, 3:点滅
    unsigned char duty_L = 0;    // 左側の明るさ用変数
    signed char direction = 5;   // 明るさの変化量(プラスで明るく、マイナスで暗く)

    while(1) {
        // --- モード切り替えスイッチ判定(2番ピンをGNDに落とすと反応) ---
        if (RA5 == 0) {
            __delay_ms(20);      // チャタリング防止
            if (RA5 == 0) {      // 押し続けられているか再確認
                while(RA5 == 0); // 指を離すまで待機
                __delay_ms(20);  // 離した後の安定待ち
                
                mode++;          // モードを1つ進める
                if (mode > 3) mode = 0; // モード0〜3を循環
                
                // モード切替時に明るさ変数をリセット
                duty_L = 0;
                direction = 5;
            }
        }

        // --- 各モードの動作実行 ---
        switch(mode) {
            case 0: // 【全消灯】
                PWM1DCH = 0;
                PWM3DCH = 0;
                break;

            case 1: // 【アナログ交互ゆらぎ】★初期起動モード
                PWM1DCH = duty_L;           // 5番ピン(L)を出力
                PWM3DCH = (unsigned char)(255 - duty_L); // 3番ピン(R)は逆位相で出力
                
                // 明るさを変化させる
                if (direction > 0) {
                    if (duty_L < 250) {
                        duty_L += 5;
                    } else {
                        direction = -5; // 上限で反転
                    }
                } else {
                    if (duty_L > 5) {
                        duty_L -= 5;
                    } else {
                        direction = 5;  // 下限で反転
                    }
                }
                __delay_ms(40); // 変化のスピード調整(ニューヨークの夜景風)
                break;

            case 2: // 【全点灯】
                PWM1DCH = 255;
                PWM3DCH = 255;
                break;

            case 3: // 【同時点滅】
                PWM1DCH = 255;
                PWM3DCH = 255;
                __delay_ms(300);
                PWM1DCH = 0;
                PWM3DCH = 0;
                __delay_ms(300);
                break;
        }
        __delay_ms(10); // ループの安定用ウェイト
    }
}

コンパイル(build)は金槌のアイコンをクリックします。PICへの書き込みはダウンロードのような下向き矢印アイコンをクリックします。読み出しはアップロードのような上向き矢印アイコンをクリックします。書き込んだPICかみ書き込みかは読みだすとわかります。以下はプログラムしたPICをhexで読みだしたファイルの中身です。

:020000040000FA
:100000000128FE2BFF3FFF3FFF3FFF3FFF3FFF3F2A
:10001000FF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3FF0
:10002000FF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3FE0
:10003000FF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3FD0
:10004000FF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3FC0
:
:10061000FF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3FEA
:10062000FF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3FDA
:10063000FF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3FCA
:10064000FF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3FBA
:10065000FF3FFF3FF501F31F2E2B2F2B362BF20907
:10066000F309F20A0319F30A0130F500F11F392BDF
:100670003A2B3F2BF009F109F00A0319F10A70082F
:1006800071040319442B452B6C2B0130F4004F2BC4
:100690000130F035F10D890B492B0130F407F11FC2
:1006A000522B532B482B71087302031D592B7008D2
:1006B0007202031C5C2B5D2B612B7008F202710827
:1006C000F33B0130F136F00C890B622B0130F40260
:1006D000031D6B2B6C2B532B75080319702B712B7F
:1006E000762BF209F309F20A0319F30A7308F100F1
:1006F0007208F0000800203021008C0023008C01DB
:10070000203024008C0021009513043020009C0030
:10071000FF309B00C0302C009300C0309900F801DE
:10072000F90120008C1A952B962BED2B0330F0004D
:100730000030F1007808013EF2000030793DF3000E
:1007400083312A2383317108F9007008F8000230E0
:10075000F7008630F6009930890BAC2BF60BAC2BEA
:10076000F70BAC2B000020008C1EB72BB82BB32B43
:10077000ED2BFF302C009200FF309800912BFA01F6
:100780007A082C0092007A0998000D30F600FC30AF
:10079000890BC82BF60BC82B0130FA077A0A031D08
:1007A000D22BD32BC02BFF30FA007A082C009200FA
:1007B0007A0998000D30F600FC30890BDD2BF60B22
:1007C000DD2B0130FA027A08031DE72BE82BD52B2D
:1007D000912B2C0092019801912B7908003A031972
:1007E000F22B912B7808003A0319B92B013A03191F
:1007F000BF2B033A0319E92B912B012820007B2BF7
:020000040001F9
:04000E00843FFF3FED
:08000000FF3FFF3FFF3FFF3F00
:00000001FF

左矢前のブログ 次のブログ右矢

posted by sakurai on March 28, 2026 #1069

ガーバーデータ及び完成したPCBを示します。

図%%.1
図1069.1 点滅回路ガーバー図

製造はいつものようにJLCPCBに依頼し、PCB製造は2.0日間で2 USD、配送料は3日で13.5 USDでした。 最終的に3月24日午前に発注して、3月27日にPCBを香港からの航空便で受け取れたので、中2日しかかかっていません。驚異的な速さです。

図%%.2
図1069.2 点滅回路PCB

左矢前のブログ 次のブログ右矢

posted by sakurai on March 26, 2026 #1067

Studio 500 3D Pop Up Wall Artの修理をすることになりました。LEDが点滅しなくなったので、点滅回路を作成します。

図%%.1
図1067.1 Studio 500

まずPICを用いて点滅シーケンスを再現します。EAGLEで作成した回路図は以下のようになります。上部のコネクタはin-circuitでPICプログラミングするためのコネクタです。

図%%.2
図1067.2 点滅回路図

以下にレイアウト図を示します。

図%%.3
図1067.3 点滅回路レイアウト図

左矢前のブログ 次のブログ右矢

posted by sakurai on December 26, 2025 #1053

Hardware Description Language Advent Calendar 2025の第4弾の記事です。タイトルは「キラキラ星アゲイン」です。 本ブログで説明した記事その他をまとめたものとなります。詳細は本ブログにて。

図%%.1
図1053.1 HDL Advent Calendar 2025 25日目

左矢前のブログ 次のブログ右矢

posted by sakurai on December 25, 2025 #1052

Hardware Description Language Advent Calendar 2025の第3弾の記事です。タイトルは「聖夜のキラキラ星をBSVで作ろう!」です。 本ブログで説明した記事その他をまとめたものとなります。詳細は本ブログにて。

図%%.1
図1052.1 HDL Advent Calendar 2025 24日目

左矢前のブログ 次のブログ右矢


ページ: