SSブログ

真夜中の訪問者2(ソフト編)

■タイミング設計について
前回、Audacityで玄関インターホンの発生周波数を測定したと書きましたが、時間変化と発生周波数の関係が読み取れません。そこでパソコンに 「Spek」という名前のソフトをインストールしました。これで時系列にスペクトラムを表示してくれます。
キーワードは、ubuntu Spek 音響スペクトラムアナライザ
s玄関エントランス・スペクトラム.png
グラフでは玄関インターホンの鳴動音。縦軸が周波数、横軸が時間軸を表しています。
このグラフ(わかりにくいです)と実際のオーディオ波形から、判定時間を決めました。
100usのサンプリング周期で8個(メモリ限界でした)なので、10KHzですが、ナイキスト周波数は5KHzとなります。1区間は5/4=1.25KHzの範囲です。玄関インターホンが鳴動すると、3区間目のレベルが設定値を越えるのをとらえて判定しています。(これが正解かどうかはわかりません)

■プログラムの流れ
●コンデンサマイクからの入力を100usの周期でAD変換
●AD変換値からゼロ点を求める
●FFT処理
●結果から2乗和の平方根を算出
●計算値が判定レベル以上ならLEDを点滅

■動作
      ●起動確認のため、通電するとLEDが2回点滅します。
      ●電池残量確認のため、30秒に1回点滅します。
      ●検知の判定は2段階で、レベルとタイミングは固定値です。
     ①マイク入力にある周波数範囲で入力があった場合、
     ②それから一定時間後に、そのマイク入力が無音を検出し、
     ③その後、一定時間後にレベル以上を検出すると、玄関の呼び出しと 判定します
     ●呼び出しがあればLEDの点滅を20秒間続けます。

■開発環境について
●対象マイコンはPIC12F1840 クロック:内部 32MHz駆動
●グラフィックLCD(ST7735液晶モジュール)はきむ茶工房さんのskST7735ライブラリをまるごと使用しています。ただし、メモリサイズの関係からフォントは使用しませんでした。(#include "font.h"をコメントアウトしています)。
●MPLAB X IDEはv5.25@linux mint 18.3
●使用コンパイラはXC8 (v.1.45) 。コンパイル後のデータメモリは206バイト(80%)プログラムメモリは3583バイト(87%)でした。
●ライターはPICKIT3を使用しています。デバッグ用ビルドではコンパイルエラーが発生し、いろいろなメッセージをみかけました。このメッセージ自体がコピーできないので原因追求がしにくかったです。
●LCD用SPI通信とデバッガとの相性が悪いようです。FFT演算結果の確認をする時はLCD表示をOFFにすることで対応しました。もっと良い方法があるのかもしれません。
●LCDが誤表示をする時があります。ライブラリの問題ではないことは確認できましたが、よくわからないのでLCDを表示する直前に割り込みを禁止しています。di()とei()はマクロで、定義はヘッダーで定義済みなので気楽に使用しています。
●configのLVP(Low voltage programming enable)はONですよ。
■プログラムリスト
/*   動作クロックは 32MHz タイマー1は10msに設定。
 *                                                                   PIC              ST7735      
 *                                                                   SCK     ←→  SCL
 *  1 VDD              8 Vss                               SDO     ←→  SDA
 *  2 LED               7 SDO                             VDD     ←→  RES
 *  3 AN3in            6 SCK                        GLCD_RS ←→  DC
 *  4 MCLR            5 GLCD_RS                VDD     ←→  BL  
 *                                              
 *                 PICKIT3のピン番号
 *                               ⑥未使用
 * 7 RA0(ICSPDAT)  ④
 * 6 RA1(ICSPCLK)  ⑤
 *                               ③GND
 *       ____                ②VDD
 * 4 RA3(MCLR)       ①    
 * 
 * LCD_TFTのスペックは ST7735の緑タブ品(基板は1.8inch 128*120 RGB と記載あり)
 *                端子を上にして左が①             接続するマイコンのpin番号
 *                 ①GND                                  ⑧ :GND
 *                 ②VCC                                   ① :VCC
 *                 ③SCL                                   ⑥ :SCL
 *                 ④SDA                                   ⑦ :SDO 
 *                 ⑤RES                                   ⑧ :VCC
 *                 ⑥DC                                     ② :LCD_RS
 *                 ⑦CS                                     ⑤ :LCD_CS
 *                 ⑧BL                                      ① :VCC
 * 
 */

#pragma config FOSC     = INTOSC //内蔵osc使用
#pragma config WDTE     = OFF //watch dog timer
#pragma config PWRTE    = OFF //Power up timer enable
#pragma config MCLRE    = ON  //Mclr/Vpp select bit
#pragma config CP       = OFF  //Code Protection bit
#pragma config CPD      = OFF   //Data Protection bit
#pragma config BOREN    = OFF  //Brown-out Reset enable bit 
#pragma config CLKOUTEN = OFF  //Clock out enable bit
#pragma config IESO     = OFF  //internal External switchover
#pragma config FCMEN    = OFF //Fall safe Clock monitor
 
#pragma config WRT    = OFF  //Flash Memory protection 
#pragma config PLLEN  = ON   //PLL enable bit 4*PLL
#pragma config STVREN = ON  //stack overflow/underflow reset
#pragma config BORV   = HI     //Brown-out reset Voltage
#pragma config LVP    = ON     //Low voltage programming enable
#include <xc.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <pic12f1840.h>

#define   xdebug 0
●LCD表示のライブラリ
LCD表示のライブラリは、きむ茶工房ガレージハウスさんの「TFT LCD(ST7735)モジュールに表示を行なう(skSDlib編)」を引用しました。

#include  "skSPIlib.h"
#include  "skST7735x.h"
//#include  "font.h"  

#define _XTAL_FREQ  32000000

#define PRESCALE  6
#define T0COUT  131

#define ON   1
#define OFF  0

#define samples 8

#define  upper_max  250
#define  lower_min    0

#define buffsize 8

#define Level1 120
#define Level2  50
#define Level3 120

int16_t   n;               // データ点数
int16_t   theta;           // m*2/n
int16_t  ar[samples];      //int32_t  入力データの実部(n点)
int16_t  ai[samples];      //int32_t  入力データ虚部(n点)
        
int16_t  spc[samples];

uint8_t incnt;
uint8_t AD_flag;
     
uint8_t spi_mode;
uint8_t acnt;
uint8_t dat;
uint8_t data;
uint8_t dat1;
uint8_t disp_mul;
uint8_t ad_mul;
uint8_t ii;
int16_t ad_buff1[buffsize];
uint8_t addata;
int16_t  mysqrt(uint16_t );
uint8_t prescaler;

//TMR1割り込み
uint16_t sec_tmr;
uint8_t  tmr_sw1;
uint8_t  tmr_sw2;
uint8_t  tmr_sw3;
uint8_t  tmr_sw4;
uint8_t  tmr_sw5;
uint8_t  tmr_sw6;
uint8_t  tmr_flg;

uint16_t sectimer1;
uint16_t sectimer2;
uint16_t sectimer3;
uint16_t sectimer4;
uint16_t sectimer5;
uint16_t sectimer6;

uint16_t xxx;
uint8_t sincnt;
uint8_t loop;
static const int8_t sin[] ={ //8*16  正弦テーブル(m点。sin(0..π))
                     0x00,0x03,0x06,0x09,0x0C,0x0F,0x12,0x15,
                     0x18,0x1C,0x1F,0x22,0x25,0x28,0x2B,0x2E,
                     0x30,0x33,0x36,0x39,0x3C,0x3F,0x41,0x44,
                     0x47,0x49,0x4C,0x4E,0x51,0x53,0x55,0x58,
                     0x5A,0x5C,0x5E,0x60,0x62,0x64,0x66,0x68,
                     0x6A,0x6C,0x6D,0x6F,0x70,0x72,0x73,0x75,
                     0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7C,
                     0x7D,0x7E,0x7E,0x7F,0x7F,0x7F,0x7F,0x7F,
                     0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7E,0x7E,
                     0x7D,0x7C,0x7C,0x7B,0x7A,0x79,0x78,0x77,
                     0x76,0x75,0x73,0x72,0x70,0x6F,0x6D,0x6C,
                     0x6A,0x68,0x66,0x64,0x62,0x60,0x5E,0x5C,
                     0x5A,0x58,0x55,0x53,0x51,0x4E,0x4C,0x49,
                     0x47,0x44,0x41,0x3F,0x3C,0x39,0x36,0x33,
                     0x30,0x2E,0x2B,0x28,0x25,0x22,0x1F,0x1C,
                     0x18,0x15,0x12,0x0F,0x0C,0x09,0x06,0x03,
                    };

static const int8_t cos[]={ //8*16 余弦テーブル(m点。cos(0..π))
                     0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7E,0x7E,
                     0x7D,0x7C,0x7C,0x7B,0x7A,0x79,0x78,0x77,
                     0x76,0x75,0x73,0x72,0x70,0x6F,0x6D,0x6C,
                     0x6A,0x68,0x66,0x64,0x62,0x60,0x5E,0x5C,
                     0x5A,0x58,0x55,0x53,0x51,0x4E,0x4C,0x49,
                     0x47,0x44,0x41,0x3F,0x3C,0x39,0x36,0x33,
                     0x30,0x2E,0x2B,0x28,0x25,0x22,0x1F,0x1C,
                     0x18,0x15,0x12,0x0F,0x0C,0x09,0x06,0x03,
                     0x00,-0x03,-0x06,-0x09,-0x0C,-0x0F,-0x12,-0x15,
                    -0x18,-0x1C,-0x1F,-0x22,-0x25,-0x28,-0x2B,-0x2E,
                    -0x30,-0x33,-0x36,-0x39,-0x3C,-0x3F,-0x41,-0x44,
                    -0x47,-0x49,-0x4C,-0x4E,-0x51,-0x53,-0x55,-0x58,
                    -0x5A,-0x5C,-0x5E,-0x60,-0x62,-0x64,-0x66,-0x68,
                    -0x6A,-0x6C,-0x6D,-0x6F,-0x70,-0x72,-0x73,-0x75,
                    -0x76,-0x77,-0x78,-0x79,-0x7A,-0x7B,-0x7C,-0x7C,
                    -0x7D,-0x7E,-0x7E,-0x7F,-0x7F,-0x7F,-0x7F,-0x7F,
                    };

static const int8_t sintbl[] ={       // 8個
                     0x00,0x5A,0x00,-0x5A,0x00,0x5A,0x00,-0x5A,  
                     };

●割り込みルーチン

void __interrupt () InterTimer( void ){
    if(INTCONbits.TMR0IF && INTCONbits.TMR0IE){
        INTCONbits.TMR0IF = 0;   //基本タイマーは100uS
        TMR0 = T0COUT;
    }

    if(PIR1bits.TMR1IF && PIE1bits.TMR1IE){
        TMR1H =  99;             //10ms timer
        TMR1L = 192;

        sec_tmr ++ ;              //電池の生存確認用に30秒に一度点灯
        if(sec_tmr > 3000){       //10ms*100 = 1sec
            sec_tmr = 0;      
            PORTAbits.RA5 = 1;     //LED ON
            tmr_sw1 = ON;
        }
        if(tmr_sw1 == ON ){        //ON時間タイマー
            sectimer1++;
            if(sectimer1 > 25){      //LED 250ms ON
                sectimer1 = 0;
                PORTAbits.RA5 = 0; //LED OFF
                tmr_sw1 = OFF;
            }
        }

        //報知のシーケンスが検出レベルに達した時(tmr_sw2がONした時) 点滅動作へ
        if(tmr_sw2 == ON){         //検出後の点滅タイマー
            sectimer2++;
            if(sectimer2 > 25){    //点滅のON時間250ms
                tmr_sw2 = OFF;
                sectimer2 = 0;
                PORTAbits.RA5 = OFF;     //LED OFF
                tmr_sw3 = ON;
            }
        }

        if(tmr_sw3 == ON){         //検出後の点滅タイマー OFF時間
            sectimer3++;
            if(sectimer3 > 40){    //点滅のOFF時間400ms
                tmr_sw3 = OFF;
                tmr_sw2 = ON;
                tmr_sw4 = ON;
                sectimer3 = 0;
                PORTAbits.RA5 = ON;     //LED 
            }
        }

        if(tmr_sw4 == ON ){  //sw2がON検出後の点滅している時間
            sectimer4++;
            if(sectimer4 > 2000){      //点滅を20秒で終了
                tmr_sw2 = OFF;
                tmr_sw3 = OFF;
                tmr_sw4 = OFF;
                sectimer4 = 0;                
                PORTAbits.RA5 = OFF;     //LED 
            }
        }

        if(tmr_sw5 == ON ){
            sectimer5++;
            if((sectimer5 >= 175) && (sectimer5 <= 300) ) {           //2375
                if( data < Level2){       //規定時間経過した時無音か
                    tmr_sw5 = OFF;
                    tmr_sw6 = ON;
                    sectimer6 = 0;
                }
            }
        }

        if(tmr_sw6 == ON) {
            sectimer6++;
            if((sectimer6 >= 150) && (sectimer6 <= 325) ) {           //3875
                if( data > Level3){   //規定時間経過した時レベルあるか
                    tmr_sw6 = OFF;
                    tmr_sw2 = ON;       //同時にLEDの点滅タイマーを起動
                    sectimer6 = 0;
                }
            }
        }
        
        if((sectimer5 > 3000)||(sectimer6 > 3000)) { //カウンターのリセット
            tmr_sw5 = OFF;
            tmr_sw6 = OFF;
            sectimer5 = 0;
            sectimer6 = 0;
        }
        
        PIR1bits.TMR1IF = 0;     
    }
}

●平方根ルーチン
以下のコードはプログラムモグモグさんの「平方根なんてビット演算ですればいいじゃない」より引用しました。重複防止のため、変数名を変えています。

        int16_t mysqrt( uint16_t xxx ){
        int16_t  aaa = 0;
        int16_t  ccc = 0;
        int16_t  yyy = 0;
        int16_t  iii = 0;
  
        int16_t  ttt = (int16_t )xxx;
  
        while(ttt >>= 1){
            ++iii;
        }
        for(iii += iii & 1; iii >= 0; iii -= 2){
            ccc = (yyy << 1 | 1) <= xxx >> iii;
            aaa = aaa << 1 | ccc;
            yyy = yyy << 1 | ccc;
            xxx -= ccc * yyy << iii;
            yyy += ccc;
        }
        return aaa;
     } 


void main(void){
        OSCCONbits.SPLLEN = 1;              
        OSCCONbits.IRCF = 0b1110;  // 内蔵発振周波数は8MHz
        OSCCONbits.SCS = 0b00;	  // クロックソースは内蔵発振or外部クロック                
        
        //IO_init
        APFCONbits.SDOSEL = 0;       // SDOに割り付け
        TRISA = 0b00011000;          //RA5:O, RA4:I, RA3:I,  RA2:O, RA1:O, RA0:O
        PORTAbits.RA5 = 0;

        ANSELAbits.ANSA4 = 1;         // AN3(RA4) only           
        TRISAbits.TRISA4 = 1;          
        
        ADCON0 = 0b00001101;           // AN3(RA4) only
        ADCON1 = 0b00010000;
        OPTION_REGbits.nWPUEN = 0;    // 弱プルアップ 0がenable  
        WPUA   = 0b00101100;

       
        //電源投入時 2回LED点滅
        PORTAbits.RA5 = 1;
        __delay_ms(200);
        PORTAbits.RA5 = 0;
        __delay_ms(400);
        PORTAbits.RA5 = 1;
        __delay_ms(300);
        PORTAbits.RA5 = 0;

if(xdebug){
        SSP1CON1bits.WCOL = 0;
        SSP1CON1bits.SSPOV = 0;
        
        SSP1CON1bits.SSPEN = 1;     //SPI disenable
        SSP1CON1bits.SSPM  = 2;      //SPI_MASTER 2:Fosc/64
        SSP1STATbits.SMP   = 0;        //sampling data:middle
        SSP1CON1bits.CKP = 0;         //アイドル時 Lで、立ち上がりで送信
        SSP1STATbits.CKE = 1;
        SSP1CON1bits.SSPEN = 1;    //SPI enable
}

 //
 // Graphic LCD (SPI) ST7735_TFT-LCD
 //
    if(xdebug){    
        GLCD_DisplayInit();
        GLCD_begin(CHIP_ST7735X | DISPLAY_TYPE_1,BLACK_SCREEN) ;
        __delay_ms(100);
        GLCD_ColorSet(0,0,63) ;        // 青色
        GLCD_Box(15,25,150,120);
        GLCD_CLS(0);                    //画面クリア 0:黒 1:白
    }
        prescaler = PRESCALE;
        OPTION_REGbits.TMR0CS = 0;
        OPTION_REGbits.TMR0SE = 0;
        OPTION_REGbits.PSA = 0;
        OPTION_REGbits.PS = prescaler - 1;
        TMR0 = T0COUT;
        INTCONbits.TMR0IE = 1;      // Timer 0 Enable
        INTCONbits.TMR0IF = 0;      // interrupt Flag clear

        //Timer1 init
        T1CONbits.TMR1ON = 1;
        T1CONbits.TMR1CS = 0;       //fosc/4
        T1CONbits.T1CKPS = 1;       //prescaler 1:2^1
        TMR1H = 99;                          //10ms timer
        TMR1L = 192;
        PIE1bits.TMR1IE = 1;
        INTCONbits.PEIE = 1;
        
        //AD secdtion
        n = samples;
        incnt = 0;
        disp_mul = 3;
        ad_mul = 3; 
        INTCONbits.GIE = 1;


    while(1){
        for(incnt = 0; incnt < samples ; incnt++){              
            ADCON0bits.GO_nDONE = 1;
            while(ADCON0bits.GO_nDONE);

            addata = ADRESH;
            if( addata > upper_max ) addata = upper_max ;
            ad_buff1[incnt] = (int16_t)addata;         
            __delay_us(100);
        }
●FFT演算処理
以下のFFTに関わるコードはBlackfin空挺団::Blog「FFTを固定小数点化するblackfin(6)」より引用しました。16ビット→8ビットのため、変数のサイズ、castの明確化などを変更しています。

            int8_t m;
            int8_t mh;
            int8_t i;
            int8_t j;
            int8_t k;

            int16_t wr;
            int16_t wi;
            int16_t xr;
            int16_t xi;
        
            int16_t rr_b;
            int16_t ii_b;
            int16_t ri_b;
            int16_t ir_b;
            
            int16_t AD_sum;
            int16_t Average;
            uint8_t ll;
            uint8_t mm;
            
            AD_sum = 0;
            theta = 64 * 2/n;
            for( acnt = 0; acnt < samples ; acnt ++){
                ar[acnt] = (int16_t) ad_buff1[acnt];

                AD_sum += ar[acnt] ;
                ai[acnt] = 0;
                
            }

            Average = AD_sum / samples ;           

            for(mm = 0; mm < samples; mm++){
                ar[mm] = (ar[mm] - Average) << ad_mul;
            }
/* FFT演算の検証のためのテスト用データをAD変換バッファに書き込む
================================================================
            //ar[]← SinWave
            for(sincnt = 0; sincnt < samples ; sincnt++){
                ar[sincnt] += ((int16_t) sintbl[sincnt]) ;
            }
=================================================================
*/

            for (m = n; m > 1; m /= 2) {
                mh = m/2;
                for (i = 0; i < mh; i++) {
                    wr = (int16_t) cos[theta * i];
                    wi = (int16_t) sin[theta * i];
                    for (j = i; j < n; j += m) {
                        k = j + mh;
                        xr = (ar[j] - ar[k]) >> 1 ;
                        xi = (ai[j] - ai[k]) >> 1 ;
                        ar[j] = (ar[j] + ar[k]) >> 1 ;
                        ai[j] = (ai[j] + ai[k]) >> 1 ;
                        rr_b =  wr * xr;
                        ii_b =  wi * xi;
                        ri_b =  wr * xi;
                        ir_b =  wi * xr;
                        ar[k] = (rr_b - ii_b) >> 8; // >>15   
                        ai[k] = (ri_b + ir_b) >> 8; // >>15
                    }
                } 
                theta *= 2;
            }
    // unscrambler 
            i = 0;
            for (j = 1; j < n - 1; j++) {
                for (k = n >> 1; k > (i ^= k); k >>= 1);
                if (j < i) {
                    xr = ar[j];
                    xi = ai[j];
                    ar[j] = ar[i];
                    ai[j] = ai[i];
                    ar[i] = xr;
                    ai[i] = xi;
                }
            }

        if(xdebug){    
                di();
                GLCD_ColorSet( 63, 63, 63) ;       // 白色63all→0all
                GLCD_Line(2,2,2,132) ;             // index yline
                GLCD_Line(2,2,162,2) ;             // index xline
                GLCD_Line(160,2,160,132) ;         // index yline
                GLCD_ColorSet( 63, 63 , 0) ;       // 黄色
                GLCD_Line( 2, 2    , 160  ,2    ); // 0
                GLCD_Line( 2, 2+127, 160  ,2+127); // 横線が 128(0x7F) のレベル
                for(ii = 0;ii < samples ;ii++ ){
                    if(ii <  4) GLCD_ColorSet( 63, 63, 0) ;              // 黄色
                    if(ii == 4) GLCD_ColorSet( 63,  0, 0) ;              // 赤色
                    if(ii >  4) GLCD_ColorSet(  0,  0,63) ;              // 青色
                    GLCD_Line( 15+ii*10, 0, 15+ii*10,3);   //目盛り
                }
                ei();

        }        
                for( ii = 0 ; ii < samples ; ii++ ){
                    spc[ii] =   ((ar[ii] * ar[ii]) + (ai[ii] * ai[ii])) << 4;  

                    if( spc[ii] < 0 )  spc[ii] = 32767 ;
                    dat = (uint8_t) mysqrt( spc[ii] );
                    if(ii == 2) data = dat;
                    dat1 = dat >> 1;               //LCD表示用データ
                    if(dat1 > 128 )  dat1 = 128;   //Yのはみ出し防止
                    
                }
       if(xdebug){
           __delay_ms(2000) ;                  //適当な数値
              di();
              GLCD_CLS(0);                    //画面クリア 0:黒 1:白
              ei();
       }
            if(data >= Level1) { 
                if((tmr_sw5 == OFF) && (tmr_sw6 == OFF)){
                    tmr_sw5 = ON;
                    sectimer5 = 0;
                } 
            }
    }
}

■もっと、どうにかしたい時は
もっと精密に設計するためには、サンプリング数をもっと増やせば可能です。メモリーサイズが多ければ周波数を細分化できます。ネットで調べていたらTI製のLMC567というCMOSトーンデコーダを見つけました。オリジナルメーカーは不明ですが、JRCのNJM567のCMOS版だそうです。形状がDIP8P。アリババで今でも手に入ります。検知周波数はCRで決めることができますが、メカニカルスイッチで切替えるのは面白くないので、デジタルポテンショメータICのマイクロチップ社MCP41010の抵抗と組み合わせるともっと精度がいいものができそうです。アナログ+デジタルのハイブリッド構成で計測器レベルで作れそうです。
作ってから気がついたのですが、電池がすぐになくなってしまいます。特性をみると、CR1220は35mAhでした。220mAhのCR2032の方がよかったかもしれません。基板スペースも問題ないですね。でも、多分、プロならスリープ状態にしておいてマイク入力レベルで目を覚ます方式にするのでしょう。
 ■謝辞
前回にも言いましたがFFT(高速フーリエ変換)についての知識はほとんどなく、そのプログラムについても全くの素人です。この課題を実現するため、下記のブログにある、プログラムリストを引用しました。特に固定小数点によるFFTについては、酔漢さんのBlackfin空挺団::blogの「FFTを固定小数点化する(1)〜(6)」では基礎的な知識からマイコン実現での問題点について丁寧に教えていただきました。でも、決して、各著作者様へのお問い合わせはしないようにおねがいします。
//********************************************************
(1)Blackfin空挺団::Blog「FFTを固定小数点化する(6)」
(2)プログラムモグモグ「平方根なんてビット演算ですればいいじゃない」
https://itchyny.hatenablog.com/entry/20101222/1293028538
(3)きむ茶工房ガレージハウス「TFT LCD(ST7735)モジュールに表示を行なう(skSDlib編)」
http://zattouka.net/GarageHouse/micon/MPLAB/18F25K22/GLCD/ST7735/ST7735x_2.htm

炭酸100%のハイボールがめっちゃうまいそうです。炭酸メーカーでバーボンのハイボールを作れるのですが、こずかいが・・・・・。今年の夏の目標にしましょう。
※このブログで書かれた内容によって生じた損害等の一切の責任を
負いかねますので、予めご了承下さい。

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。