// Web掲載のソース:"main.c"に変更する // メロディのソースは、末尾に /******************************************************** * Version_13 (間欠時間の設定もAD変換で行う) * 連続間欠タイマー + 得点表示 2022.03.07〜2023.08.05 * Pic:16F1827 MPLAB IDE Ver8.84 HI-TECH C v9.83 * 計測時間設定は、VR(可変抵抗)により行う * インターバル時間をロータリーSWとRで設定する * インターバル設定は、最大20秒(0,5,10,15,20) * 表示は大型7segLED(interface:TM1637)アノード・コモン および * 小型4dig7seg(TM1637,コロン有,DP無し) * メロディはピアノ(減衰)音を出力するプログラムを利用 * メロディ音源:RA3 ブザー音源:RA4 * RA0:AD変換(計測時間設定) RA1:AD変換(インターバル時間の設定) * RA2:タイマー⇔カウンターの切替 * RA5:リセット RA7:開始/停止SW (RA6:接続無し) * RB0〜3:カウンタ用 RB4,5:前面大型7segLED用 RB6,7:上面小型7seg * タイマ0:1秒カウント用 タイマ1:メロディ用 タイマ2:PWM * 30秒以内は5秒、2分以内は10秒きざみ、越えると30秒きざみの時間設定 **********************************************************/ // 音が減衰する程度 指定値(ms)で1/16減少 #define EnvelopeConst 50 // 音符と音符の間の無音時間(ms) #define Silent 30 #include #include "ohkinakurino.h" // 『大きな栗の木の下で』 // const unsigned int Music[] = {楽譜データ} #define _XTAL_FREQ 8000000 // 8MHz // 音源:RA3(CCP3) #define SW RA7 // 開始/停止SW #define BzPort RA4 // ブザー音 #define TRIS_Bz TRISA4 // 出力切替 #define CLK RB4 // 前面大型用 #define DIO RB5 // #define CLK2 RB6 // 上面小型用 #define DIO2 RB7 // /***** コンフィギュレーションの設定 ********/ __CONFIG(FOSC_INTOSC // INTOSCIO oscillator I/O function & WDTE_OFF // Watchdog Timer disabled & PWRTE_ON // Power-up Timer enabled & BOREN_ON // Brown Out enabled & MCLRE_ON // MCLR RA5はリセット & CP_OFF // Program memory code protection is disabled & CPD_OFF // データメモリーを保護しない(OFF) & CLKOUTEN_OFF // CLKOUTピンをRA6ピンで使用する(OFF) & IESO_OFF // Internal External Switchover mode is disabled & FCMEN_OFF // Fail-Safe Clock Monitor is disabled & WRT_OFF ); // Flashメモリーを保護しない(OFF) __CONFIG(PLLEN_OFF // 動作クロックを32MHzでは動作させない(OFF) & STVREN_ON // Stack Overflow/Underflow will cause a Reset & BORV_LO // 電源電圧降下常時監視電圧(2.5V)設定(LO) & LVP_OFF ); // 低電圧プログラミング機能使用しない(OFF) // 音の高さを決める定数 for 8MHz Fosc PWM Freq 16.525kHz const unsigned int dW_tbl[] = { // Do, Do#, Re, Re#, Mi, Fa, Fa#, So, So#, Ra, Ra#, Si, 0,0x112,0x122,0x133,0x146,0x159,0x16E,0x183,0x19B,0x1B3,0x1CD,0x1E8,0x205, //12 0x224,0x245,0x267,0x28C,0x2B3,0x2DC,0x307,0x336,0x366,0x39A,0x3D1,0x40B, 0x449,0x48A,0x4CF,0x518,0x566,0x5B8,0x60F,0x66C,0x6CD,0x735,0x7A3,0x817, 0x892,0x915,0x99F,0xA31,0xACD,0xB71,0xC1F,0xCD8,0xD9B,0xE6A,0xF46,0x102E, 0x1125,0x122A,0x133E,0x1463,0x159A,0x16E3,0x183F,0x19B0,0x1B37,0x1CD5,0x1E8C,0x205D, 0x224A,0x2454,0x267D,0x28C7,0x2B34,0x2DC6,0x307E,0x3361,0x366F,0x39AB,0x3D19,0x40BB }; // 0x892(index 37) が中心のド(60 0x3E) ,0xD9B はラ (440Hz) /* 7seg用DATA -gfedcba→8ビット*/ char const LED_SEG[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x67 }; // タイマー用 unsigned int Time, Time2; // 設定秒数(繰り返し,インターバル) unsigned int g_time; // ADCから得た計測時間 unsigned char Mode; // 処理モード: 0〜3 unsigned char Count; // 20mSのカウント(50回で1秒) unsigned char s1,s2,s3,s4,s5; // 大型7seg用表示文字 unsigned char n1,n2,n3,n4; // 小型7seg用 〃 // 前面大型7seg用 void S7_Start(void); void S7_Stop(void); void S7_init(); // 初期化 void S7_Hyoji(); // 表示 unsigned char S7_Out(unsigned char data); // シリアル書出し // 上面小型7seg用 void S7_Start2(void); void S7_Stop2(void); void S7_init2(); void S7_Hyoji2(); unsigned char S7_Out2(unsigned char data); // 表示する文字を設定サブ void keisan(void); // 秒→分:秒 void Set_7seg(); // カウンタ表示データへ // 各フラグ unsigned char BF, chflg; // 開始ブザーと1秒経過のフラグ unsigned char melody_on; // メロディonのフラグ unsigned char melody_stop; // メロディoffのフラグ // カウンター用 unsigned char RIGHT,LEFT; // 得点の変数(右,左) unsigned char SIDE; // サーブ側表示 R=>0, L=>1 unsigned char colon; // サーブ側変動時:点灯、連続得点:消灯 unsigned char Tact; // 得点用タクトスイッチ // メロディ用 unsigned int accWave,incWave; unsigned char amp,wave; void melody(); // オルゴール演奏 char set_interval(void); // インターバル時間(秒数)の取得 void bzr1(void); // プ void bzr2(void); // ピ void delay_10us(unsigned char t1); // 10us遅延 void delay_10ms(unsigned char t2); // 10ms遅延 unsigned int GetData(); // ADCからデータ取得 unsigned char keysearch(); // どのキー? unsigned char getkey(); // 確認5回 // メロディ用変数 unsigned int Track; // 音符位置 unsigned int Note; // 音符 unsigned char tempo; // テンポ unsigned char Len; // 演奏長さ char AmpCnt = 25; // 振幅調整 char TmpCnt = 65; // テンポ調整 char TmpFlg = 0; // テンポフラグ char SltCnt = 20; // 無音時間 char SltFlg = 0; // 無音フラグ char ampNext; // 次音符音量 void main(void) { OSCCON = 0b01110000;// 内部クロック 8Mhz(右端は:10,00どちらも可) ANSELA = 0x03; // RA0,RA1をアナログ(ADC) ANSELB = 0x00; // 全てデジタルIO TRISA = 0xFF; // 基本は入力設定(RA3,4はその都度出力に) TRISB = 0x0F; // 0-3:入力、4,5,6,7 は、I2c出力 // CM1CON0 = 0x00; // コンパレータ不使用 // ADCON0 = 0x00; デフォルト:RA0(0x04→RA1) 使う時=>0x05(有効化) ADCON1 = 0xA0; // Fosc/32,右詰,基準(Vdd-Vss) // タイマー0の設定 秒カウントダウン・タイマー用 OPTION_REG = 0x87; // 内部プルアップ無し、プリスケーラ 1/256 // TOCS=0,TOSE=0,PSA=0,PS2〜0=1:1:1 INTCON = 0xC0; // GIE=1, PEIE=1; T0IE=0, T0IF=0 TMR0 = 0x64; // 初期値:100 0.5μS×(256-100)×256 => 約20mS T0IE = 0; // Timer0 始動はまだ // Timer1 の設定 メロディの出力 T1CON = 0b01000000; // Fosc ps 1/1 TMR1ONまだ TMR1 = 0xE100; // +7936 (0.992ms) で Carry TMR1IF = 0; // Timer1フラグクリア // PWM, Timer2 の設定 減衰音の作成 CCPTMRS = 0b00000000;// CCP3をTimer2に割当て CCP3CON = 0b00001100;// CCP3をPWMモードに設定 // (かつCCPR3Lの下位2ビットを0に設定) T2CON = 0b00000000; // Timer2 OFF PreS 1/1 PR2 = 0x7F; // 繰返し周波数 15.625KHz TMR2IF = 0; // Timer2フラグクリア TMR2IE = 1; // Timer2割込み有効 PEIE = 1; // ペリフェラル割込み有効 GIE = 1; // 全割込み処理を許可する /**** メインループ *****/ S7_init(); S7_init2(); /*** 機能切替SW(RA2)により、タイマーとカウンターに動作分岐 ***/ if(RA2 == 1){ // 機能切替スイッチ=off(デフォルト:1) // タイマーの場合 : 変数初期化 Count = 0; // 50回で1秒 BF = 0; // 開始ブザーフラグ Mode = 0; // 動作モード(0:設定 1:開始 2:動作中 3:インターバル) while(1){ if(SW == 0){ // 開始/停止ボタン(RA7)が押されたら while(SW == 0); // チャタリング回避 delay_10ms(2); if(Mode == 0 && Time > 0){ Mode = 1; // Timeが0でなければ開始 }else{ T0IE = 0; // タイマ0停止 melody_stop = 1;// メロディ中止フラグ Mode = 0; } } switch(Mode){ case 0: // 時間設定 // ここで AD変換で、VRから値(0-1023)を得る ADCON0 = 0x00; // AD変換:RA0を指定 g_time = GetData(); // VRから値(0-1023)を得る g_time = (long)g_time * 301 / 1023; // 最大300秒(5分) if(g_time > 120)g_time = g_time / 30 * 30;// 2分以上は30秒ごと else if(g_time > 30)g_time = g_time / 10 * 10; // 30秒−2分は10秒 else g_time = g_time / 5 * 5; // 30秒以下は5秒ごと Time = g_time; keisan(); S7_Hyoji(); // 前面表示 S7_Hyoji2(); // 上面表示 break; case 1: // 開始へ T0IE = 1; // タイマ0始動 Mode = 2; BF = 1; // ブザーフラグ break; case 2: // 設定秒の計測中 if(BF == 1){ bzr2(); // 開始のブザーを鳴らす delay_10ms(3); // ピッピッ bzr2(); BF = 0; } if(0 < Time && Time < 4){ // 残り3秒からプッ if(chflg == 1){ // 1秒経過したら chflg = 0; bzr1(); } } break; case 3: // インターバル中 if(melody_on == 1){ melody_on = 0; // フラグをリセット melody(); } break; } // end_switch keisan(); S7_Hyoji(); S7_Hyoji2(); } // end_while1 }else{ // RA2=0(on)の場合 // カウンターの場合 PORTB = 0x0F; SIDE = 2; // 最初はどちらでもない colon = 1; // コロン表示 while(1){ Tact = getkey(); // どのキーを押した? switch(Tact){ case 1: // 左得点 bzr1(); LEFT++; if(LEFT > 99)LEFT = 0; if(SIDE != 1){ SIDE = 1; // 左DOT点灯 colon = 1; // サイドが変わったら }else{ // コロン点灯 colon =0; } while(RB0 == 0); delay_10ms(10); // タクトスイッチの誤動作防止 break; case 2: // 左減点 bzr2(); if(LEFT)LEFT--; // 0なら減点無し while(RB1 == 0); delay_10ms(10); break; case 3: // 右減点 bzr2(); if(RIGHT)RIGHT--; // 0なら減点無し while(RB2 == 0); delay_10ms(10); break; case 4: // 右得点 bzr1(); RIGHT++; if(RIGHT > 99)RIGHT = 0; if(SIDE != 0){ SIDE = 0; // 右DOT点灯 colon = 1; }else{ colon = 0; } while(RB3 == 0); delay_10ms(10); break; } // end_case Set_7seg(); S7_Hyoji(); S7_Hyoji2(); } // end_while2 } // end_else } // end_main // 割込み処置 ----------------------------------------------------- void interrupt isr(void){ // Timer0 は秒数カウント、Timer2はメロディ用 if(TMR2IF){ // Timer2 割込みを確認 TMR2IF = 0; // Timer2 フラグ リセット accWave += incWave; // 周期計算 if((STATUS & 0x01)==1)wave ^= 1; // キャリが出れば、波形反転 if(wave)CCPR3L = amp; // 波形ONなら、 出力あり else CCPR3L = 0; // OFFなら、出力なし } if (T0IF == 1){ // タイマー0の割込み発生か? TMR0 = 0x64; // タイマー0の初期化 Count++; // 割込み発生の回数をカウントする T0IF = 0; // タイマー0割込フラグをリセット if (Count >= 50){ // 割込みを50回カウントすると約1秒 Count = 0; Time--; chflg = 1; // 1秒経過フラグ } if(Mode == 3 && Time == 1)TRISA3 = 1;// 残1秒でメロディ消す if(Time==0){ if(Mode == 2){ // 通常のタイムアップ? Time2 = set_interval(); // インターバル時間をセット if(Time2 == 0){ // インターバル無しなら Time = g_time; // 繰り返し時間をセット Mode = 1; }else{ Time = Time2; melody_on = 1; Mode = 3; // インターバル・モードへ } }else if(Mode == 3){ // インターバルの終了なら melody_stop = 1; // メロディ中止フラグ Time = g_time; Mode = 1; } // end_if(Mode == 2) } // End_if(Tome==0) } //if (T0IF == 1) } // RA1からインターバル時間を取得 char set_interval(){ unsigned int k_time; ADCON0 = 0x04; // AD変換:RA1を指定 k_time = GetData(); // VRから値(0-1023)を得る k_time = (long)k_time * 23 / 1023; // 一工夫 if(k_time > 19)k_time = 20; // 最大20秒 k_time = k_time / 5 * 5; // 5秒毎の数値に return(k_time); } /* メロディ関数 */ void melody(){ unsigned char Step; TRISA3 = 0; // 音源を出力に Track = 0; melody_stop = 0; // フラグリセット Step = 1; TMR1ON = 1; while(1){ //------------ 1ms 毎のタイミング処理 ---------------------- if(TMR1IF){ // 1ms 毎に実施 TMR1H = 0xE1; // 次の 1ms を設定 TMR1IF = 0; // フラグクリア //------- 振幅調整 50ms ----------------------------------- if(AmpCnt-- == 1){ AmpCnt = EnvelopeConst; // 音量を 50ms毎に amp = (int)amp * 15/16; // 音量を -6% する } //------- テンポ調整 ----------------------------------- if(TmpCnt-- == 1){ TmpCnt = tempo; // テンポ毎に TmpFlg = 1; // テンポフラグをセット } //------- Silent時間 ----------------------------------- if(SltCnt-- == 1){ // 消音時間になれば SltFlg = 1; // 消音フラグをセット } } if(melody_stop == 1)Step = 6; if(SW == 0){ // SWが押されたなら Step = 6; // 終了処理へ Mode = 0; while(SW == 0); delay_10ms(3); } if(chflg == 1){ chflg = 0; keisan(); S7_Hyoji(); S7_Hyoji2(); } //------------------- 主フロー制御 --------------- switch(Step){ case 1: // ====== 楽譜の設定 ====== if(Music[Track]==0xFFFF)Track=0; // 楽譜終了なら先頭に tempo = 7500/Music[Track++]; // 楽譜のテンポ取得 TMR2ON = 1; // Timer2 on TmpCnt = tempo; // テンポセット TmpFlg = 0; // フラグりセット Step = 2; break; case 2: // ====== 音符の設定 ====== Note = Music[Track++]; // 音符を取得 if(Note == 0xFFFF){ // 曲の終了なら Track = 0; // 先頭に Step = 1; break; } Len = Note & 0x00FF; // 音符の長さ取得 Note = Note >> 8; // 音高を取り出す if(Note){ // 音符なら incWave = dW_tbl[Note - 23]; // 音高を繰返し時間に変換 ampNext = 0x7F; // 音量最大 }else{ // 休符なら incWave = 0; // 繰返し なし ampNext = 0; // 音量OFF } Step = 3; break; case 3: // ====== 音符の演奏開始 ====== if(TmpFlg){ // テンポ待ち TmpFlg = 0; // テンポフラグリセット amp = ampNext; // 音量最大 AmpCnt = EnvelopeConst; // 音量減少リセット Step = 4; } break; case 4: // ====== 音符の演奏継続 ====== if(TmpFlg){ // テンポ待ち TmpFlg = 0; // テンポフラグリセット if(Len-- == 2){ // 音符終了なら SltCnt = tempo - Silent; // 消音時間をセットし SltFlg = 0; // 消音フラグをリセット Step = 5; } } break; case 5: // ====== 音符の演奏終了 ====== if(SltFlg){ // 時間を待つ amp = 0; // 音量OFF Step = 2; // 次の音符取得へ } break; case 6: // ====== 楽譜の演奏終了 ====== TMR1ON = 0; // Timer1 Off TMR2ON = 0; // Timer2 Off break; } // end_switch if(Step == 6){ TRISA3 = 1; // RA3を入力にして return; } } // end_while } // end_melody // 計算(秒→7segデータに) // s1〜s5は前面大型7seg、n1〜n4は上面小型7seg // コロンは(大型)s3のa_seg(0x01)と(小型)n2の最上位ビット(0x80) void keisan(void){ // s1 = LED_SEG[Time / 600];// 10分の桁の場合 s1 = 0x00; // 10分の桁は無 n1 = 0x00; if(Time < 60){ // 1分未満は s2 = 0x00; // 1分の桁:空(大型前) n2 = 0x00; // 1分の桁:空(小型上):コロン無 s3 = 0x00; // コロン:無(大型前) }else{ s2 = LED_SEG[Time / 60]; s3 = 0x01; // コロンあり(大型前) n2 = LED_SEG[Time / 60]; n2 |= 0x80; // コロンあり(小型上) } if(Time < 10){ // 10秒未満なら s4 = 0x00; n3 = 0x00; }else{ s4 = LED_SEG[Time % 60 / 10]; n3 = LED_SEG[Time % 60 / 10]; } s5 = LED_SEG[Time % 10]; n4 = LED_SEG[Time % 10]; } // カウンター用・表示データの設定(LEFT RIGHTの数値→7segデータに) void Set_7seg(){ // SIDE:0 右 SIDE:1 左 ::後ろから見て // 3桁目(0x01:コロン 0x20:右赤  0x40:左赤) // 上側の7segの表示は左右が逆になる。 // 上側の7segLEDでは、サーブ側の表示は点滅で代替する。 if((LEFT / 10) == 0){ s1 = 0x00; n3 = 0x00; } else{ s1 = LED_SEG[LEFT / 10]; n3 = LED_SEG[LEFT / 10]; } s2 = LED_SEG[LEFT % 10]; n4 = LED_SEG[LEFT % 10]; if((RIGHT / 10) == 0){ s4 = 0x00; n1 = 0x00; } else{ s4 = LED_SEG[RIGHT / 10]; n1 = LED_SEG[RIGHT / 10]; } s5 = LED_SEG[RIGHT % 10]; n2 = LED_SEG[RIGHT % 10]; if(colon == 0){ s3 = 0x00; }else{ // コロン点灯 s3 = 0x01; n2 |= 0x80; // 2桁目のDPの位置 } // サーブ側の表示(大型のみ) if(SIDE == 0){ // 右側 s3 |= 0x20; // fの位置 }else if(SIDE == 1){// 左側 s3 |= 0x40; // gの位置 } } // 大型7セグ初期化 void S7_init(){ S7_Start(); // スタート S7_Out(0x40); // 移動表示モード S7_Stop(); S7_Start(); S7_Out(0x8B); // 明るさ指定(12/16) S7_Stop(); } // 大型7セグに表示 void S7_Hyoji(){ S7_Start(); S7_Out(0xC0); // 開始位置左端 S7_Out(s1); // 左端 10分 S7_Out(s2); // 分 S7_Out(s3); // コロン S7_Out(s4); // 10秒 S7_Out(s5); // 右端 S7_Stop(); } /*** 通信 Start ****/ void S7_Start(void){ /* CLk,DIOは通常:High */ NOP(); DIO = 0; // 先にDIO=Low NOP(); } /**** 通信 Stop ****/ void S7_Stop(void){ CLK = 0; // CLK Low NOP(); DIO = 0; // DIO Low NOP(); CLK = 1; // 先にCLKをHigh NOP(); DIO = 1; // 後からDIOをHigh } /*** I2Cで1バイト出力(要:9ビット目CLK ON/OFF) ***/ // クロック周波数8MHzでは速すぎるので NOP() が必要 unsigned char S7_Out(unsigned char data){ char i; for(i=0; i<8; i++){ // 8回繰り返し CLK = 0; // CLK Low NOP(); // TM1637にとって8MHzが速すぎる DIO = (data>>i) & 0x01; // ビット送信 NOP(); CLK = 1; // CLK Highに戻す NOP(); } CLK = 0; // ※要9ビット目 NOP(); CLK = 1; // ACK:low NOP(); } // 小型7セグ初期化 void S7_init2(){ S7_Start2(); // スタート S7_Out2(0x40); // 移動表示モード S7_Stop2(); S7_Start2(); S7_Out2(0x88); // 明るさ指定(9/16) S7_Stop2(); } // 小型7セグに表示 void S7_Hyoji2(){ S7_Start2(); S7_Out2(0xC0); // 開始位置左端 S7_Out2(n1); // 左端 10分 S7_Out2(n2); // 分 S7_Out2(n3); // 10秒 S7_Out2(n4); // 右端 秒 S7_Stop2(); } /*** 通信 Start(小型) ****/ void S7_Start2(void){ /* CLk,DIOは通常:High */ NOP(); DIO2 = 0; // 先にDIO=Low NOP(); } /**** 通信 Stop(小型) ****/ void S7_Stop2(void){ CLK2 = 0; // CLK Low NOP(); DIO2 = 0; // DIO Low NOP(); CLK2 = 1; // 先にCLKをHigh NOP(); DIO2 = 1; // 後からDIOをHigh } /*** (小型)I2Cで1バイト出力(要:9ビット目CLK ON/OFF) ***/ // クロック周波数8MHzでは速すぎるので NOP() が必要 unsigned char S7_Out2(unsigned char data){ char i; for(i=0; i<8; i++){ // 8回繰り返し CLK2 = 0; // CLK Low NOP(); // TM1637にとって8MHzが速すぎる DIO2 = (data>>i) & 0x01; // ビット送信 NOP(); CLK2 = 1; // CLK Highに戻す NOP(); } CLK2 = 0; // ※要9ビット目 NOP(); CLK2 = 1; // ACK:low NOP(); } // 遅延タイマ void delay_10us(unsigned char t1){ while(t1){ __delay_us(10); // 10μsec t1--; // 10μsec x time } } void delay_10ms(unsigned char t2){ while(t2){ __delay_ms(10); // 10msec t2--; // 10msec x time } } // A/D変換:10回の平均値 unsigned int GetData(){ unsigned int hei, kei; unsigned char i; kei = 0; for(i=0;i<10;i++){ ADON = 1; delay_10us(1); ADGO = 1; while(ADGO); kei = kei + (ADRESH*256 + ADRESL); } hei = kei / 10; return(hei); } // 押されている(=0の)SWを探す unsigned char keysearch(){ unsigned char tsw; switch (PORTB & 0b00001111){// RB0〜RB3 case 0b00001110:// 押されたビットが0になる tsw = 1; break; case 0b00001101: tsw = 2; break; case 0b00001011: tsw = 3; break; case 0b00000111: tsw = 4; break; default: tsw = 0; } return (tsw); } // 5回連続で「押」を確認したら、その値を返す unsigned char getkey(){ unsigned char newval, oldval, cnt; oldval = 0x00; while(1){ for(cnt = 0; cnt < 5; cnt++){ newval = keysearch(); if(newval != oldval){ cnt = 0; oldval = newval; } delay_10us(10); } return(newval); } } // ブザー用ルーチン void bzr1(void){ // 残り3秒および得点のプ TRIS_Bz = 0; // 出力指定 int i; for (i = 0; i < 80 ; i++) { BzPort = 1 ; delay_10us(60); BzPort = 0 ; delay_10us(60); } TRIS_Bz = 1; // 入力に戻す } void bzr2(void){ // 開始および減点のピ TRIS_Bz = 0; int i; for (i = 0; i < 60 ; i++) { BzPort = 1 ; delay_10us(40); BzPort = 0 ; delay_10us(40); } TRIS_Bz = 1; } //[EOF] //を削除 // ここからはメロディ用のソース // "ohkinakurino.h"のファイル名で同一フォルダに const unsigned int Music[] = { 130, // 大きな栗の木の下で 0x3C08,0x3C04,0x3E04,0x4004,0x4004,0x4308,0x4004,0x4004, 0x3E04,0x3E04,0x3C08,0x0008,0x4008,0x4108,0x4308,0x4808, 0x4508,0x4808,0x430C,0x0004,0x4808,0x4808,0x4708,0x4308, 0x4504,0x4504,0x4504,0x4504,0x4308,0x0008,0x3C08,0x3C04, 0x3E04,0x4004,0x4004,0x4308,0x4004,0x4004,0x3E04,0x3E04, 0x3C0C,0x0004, 0xFFFF, 0xFFFF, };