UMEHOSHI ITA TOP PAGE    COMPUTER SHIEN LAB

UMEHOSHI IT (my_sys.cと.my_sys.h)

my_sys.hのソース

001
002
003
004
005
006
007
008
009
010
011
012
013
#ifndef _MY_SYS_H    /* Guard against multiple inclusion */
#define _MY_SYS_H

#include "my_beep.h"

extern int core_once_count1_val; // 0になるまでコアタイマでダウンカウント
extern int core_once_count2_val; 
extern int core_once_count3_val; 

void init_main();
void init_interrupt();

#endif /* _MY_SYS_H */

my_sys.cのソース

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
/*
 * ウメ・エディット・プログラム実現用のシステム部分
 * 起動関連の処理
 * タイマ関連 割り込み関連の初期指定
 * PWMの初期化ルーチン
 * ADコンバータの初期化ルーチン
 */

#include <xc.h>
#include <stdio.h>
#include <proc/p32mx270f256b.h>
#include "my_app.h" 
#include "my_usb_cmd.h" 
#include "my_adc.h" 
#include "my_uart.h"
#include "my_sys.h"
#include "common.h"

/*****************************************************
 *  グローバル変数
 ****************************************************/
unsigned int temp;// デバック確認用

// ESP32-WROOM-32Dの起動時のメッセージ出力を止める細工を20201005に追加
int core_once_count1_val = 880; // 0になるまでコアタイマでダウンカウント(1秒)
int core_once_count2_val = 1760; // 0になるまでコアタイマでダウンカウント(2秒)
int core_once_count3_val = 2640; // 0になるまでコアタイマでダウンカウント(3秒)
int core_once_count4_val = 3520; // 0になるまでコアタイマでダウンカウント(4秒)

// 割り込みルーチンとウメシステム情報のテーブル
void (*handlers_table[(0x1000>>2)-4])(void) __attribute__ (( persistent, address(_PTR_HANDLERS) ));

// RAMのプログラミングや情報記憶域領域
char ram_area1[0x3000] __attribute__ (( persistent, address(_PTR_RAM_AREA1) ));
char ram_area2[0x1000] __attribute__ (( persistent, address(_PTR_RAM_AREA2) ));
char ram_area3[0x0F00] __attribute__ (( persistent, address(_PTR_RAM_AREA3) ));

// 割り込みルーチンとウメシステム情報のテーブルの先頭ポインタ
void (**handlers)(void)= (void (**)(void) )handlers_table;

static int led_D1=0;//LED D1の初期値

int power_on_flag = 0; // パワーオンリセットで1、リセット時は0 追加[2023-4]

/* =============================================================================
 *  main内部の最初に呼ばれる。( SYS_Initialize ( NULL );の前で呼ばれる)
 * =============================================================================
 */
void init_main()
{
    //ANSELB:指定ビット0にするとデジタル、1でアナログ(デフォルト)として使う。
    ANSELBCLR =  0x0000E3BC; //15,14,13,9,8,7,5,4,3,2を0にする。
                             // 1110 0011 1011 1100
    ANSELBCLR = ~0x00000DB3; // 0への指定ビットをデジタルとして使う
    ODCB = 0x0; // オープンドレインを使わない。 

    // TRISB 1にすると入力、0にすると出力
    TRISBCLR =  0x0000E22C; // 出力指定 1110 0010 0010 1100
    TRISBSET =  0x00000190;//  入力指定 0000 0001 1001 0000
       
    // CPU 命令アクセスバスエラービット バスエラー例外を無効にする
    ((__BMXCONbits_t *)& BMXCON )->BMXERRIS = 0;
    
    // バスマトリクス調停モードビット モード0
    ((__BMXCONbits_t *)& BMXCON )->BMXARB = 0;
       
    // メモリ構成の設定 「0x80004000」?をプログラミング用に使う
    BMXDKPBA = 0x00004000;//16 KB のカーネルデータ 「0x80004000」    
    BMXDUDBA = BMXDKPBA+0x0000C000;//48 KB のカーネルプログラム
    BMXDUPBA = BMXDUDBA;//ユーザデータのサイズ = 0、ユーザプログラムのサイズ = 0 
    // メモリ構成の設定はここまで
    
    extern void init_handle_area ();//ハンドラ・テーブル と ユー・ラム・エリア 初期用 
    // このソースの最後で、「ウメ・エディットプログラム」インターフェイス用に定義!)
    init_handle_area (); // ハンドラ・テーブル と ユー・ラム・エリア 初期     
    //  (各種インターフェイス用記憶域、割込みテーブルの初期化などが初期化)
}
 
/*******************************************************************************
 * 
 *  各割込みのサンプル関数
 * 
 ******************************************************************************/

void dummy_function() {  }// ダミー関数

void dummy_init_function() {// handlers[_IDX_INIT_SUB_FUNC]デフォルト値
    _RB15 = led_D1; // D1 LED の初期設定
    asm("NOP");
}// ダミー関数

volatile unsigned int core_wait_down_count __attribute__((section("sfrs")));
//uint8_t core_wait_down_count;//割り込みで変更される変数は、上記の宣言が必要
// 上記を使った待機関数(コアタイマの割り込みでカウントされる変数を利用して待機する。)
void core_wait(int cnt0){
   if(core_wait_down_count == 0){
        core_wait_down_count= cnt0;
    }
    while(core_wait_down_count > 0){
    }
 }
 
// onに変化してからn回連続onが続いた時に1を、そうでなければ0を返す。
// また、それを記憶する変数(押し続けても、1回しかtrueにならない分、少し遅れる)
static int switch2 = 0;
int is_on_sw2(int n){ // default コアタイマで呼び出している。
    static int push = 0;
    static int cnt = 0;
    push = (PORTB & 0x80) == 0;
    if( switch2 != push ){
         cnt++;
    } else {
        cnt = 0;                    
    }
    if(cnt == n) {
        switch2 = push;//しっかり変化したと判断(n回分の遅れが生じる)
        return switch2;
    }
    return switch2;
}

// SW2の状態を返すグローバル関数 (押すと1になる)●
int get_switch2_state(){
    return switch2;
}

void core_timer_sub_1()// 初期サンプルのビープ振動処理, SW2チェック--------------
{    
    // 起動時時SW2操作の分岐や、ESP32-WROOM-32Dの起動時のメッセージ出力を止める細工
    if(core_once_count1_val != 0) core_once_count1_val--;
    if(core_once_count2_val != 0) core_once_count2_val--;
    if(core_once_count3_val != 0) core_once_count3_val--;
    if(core_once_count4_val != 0) core_once_count4_val--;
    if(core_wait_down_count != 0) core_wait_down_count--;
    
    //別途に1秒時にUART受信あれば、UARTへ改行を送信して2秒間のUART受信を無視している
    
    if(core_once_count3_val==1){//3秒のタイミングで1回だけ実行
        U1STAbits.OERR = 0;     

        if( _RB7 == 0 || _UME_THROUGH_MODE){//約2秒後の瞬間
            // _RB7 がLow(SW2が押されていいる)または、スルーモード指定がある?           
            
            //_RB15 = ! _RB15;// // D1 LED 反転 (点燈から消灯へ)
            _RB15 = 0;  // :202503 (消灯へ)
            asm("NOP");     
                       
            // UARTスルーモードへ移行
            handlers[_IDX_MY_APP_TASKS] = (void *)My_APP_Tasks_Through;
            APP_State_Reset();
            init_outBuffers(); //USB出力用リングバッファ関連変数 の初期化
            ringbuf_reset(&uartSndBuf);
            ringbuf_reset(&uartRecBuf);
            clear_beep_code();
            
            // 下記のフロー制御を使うとESP32-WROOM-32Dのesptool.pyが使えない
            //U1MODEbits.RTSMD = 0; // UxRTS ピンモード選択をフロー制御モード
            //U1MODEbits.UEN = 2;//UxTX、UxRX、UxCTS、UxRTS ピンを有効にして使う
        }
    }

    if(core_once_count4_val==1 && _RB7 == 0){//_RB7 がLow(SW2が押されていいる)
        // UART のコマンドモードへ移行
        //_RB15 = ! _RB15;// // D1 LED 反転 (点燈から消灯へ)
        _RB15 = 0;  // :202503 (消灯へ)
        asm("NOP");  
          
        handlers[_IDX_MY_APP_TASKS] = (void *)My_APP_Tasks;
        init_outBuffers(); //USB出力用リングバッファ関連変数 の初期化
        handlers[_IDX_DEF_POLLS_UART] = handlers[_IDX_CMD_POLLS_UART];
        
        // RN42のプログラム転送で、下記のフロー制御が必要
        U1MODEbits.RTSMD = 0; // UxRTS ピンモード選択をフロー制御モード
        U1MODEbits.UEN = 2;//UxTX、UxRX、UxCTS、UxRTS ピンを有効にして使う
    }
    
    void base_beep();// この関数内部で、ブザーの振動のON/OFF制御をしている。
    base_beep();// ビープ音の音色(グローバル変数beep_onでブザーをON、OFFしている。)
    
    void beep_code_switching();// グローバル変数beep_onを変更してON/OFF指示
    beep_code_switching();// 4bitコードを音にする。 (初期は440Hzビープ)
    
    int is_on_sw2(int n);    
    is_on_sw2(50);  // スイッチ SW2の監視関数
    //temp = get_switch2_state();  //SW2の状態取得可能。
}

// コアタイマーサンプル関数-------------------------------------------------------
void core_timer_umeFunc_1(){
    unsigned long ct_count = _CP0_GET_COUNT();
    unsigned long period = _UM_CP0_SET_COMPARE;  
    handlers[_IDX_CORE_TIMER_SUB_FUNC](); // 上記core_timer_sub_1()がデフォルト.    
    // update the Compare period
    period += ct_count;
    _CP0_SET_COMPARE(period);

    IFS0CLR = _IFS0_CTIF_MASK; // 割り込み要求フラグをクリア
}


//  Timer1 の割り込みから呼びだされるサンプル関数----------------------------------
void timer1_umeFunc1_1(){
    IFS0CLR = 0x00000010; // Clear the timer interrupt status flag

    void beep_cycle_switching();
    beep_cycle_switching();  // サウンド再生時の音の長さ制御がデフォルト
}

//  Timer2 の割り込みから呼びだされるサンプル関数----------------------------------
void timer2_umeFunc1_1(){
    IFS0CLR = 0x00000200; // Clear the timer interrupt status flag
}

// 各コンペアの割り込み関数
void compare5_umeFunc(){   
    IFS0CLR= _IFS0_OC5IF_MASK; // Clear the OC5 interrupt flag
}
void compare1_umeFunc(){   
    IFS0CLR= _IFS0_OC1IF_MASK; // Clear the OC1 interrupt flag
}
void compare3_umeFunc(){   
    IFS0CLR= _IFS0_OC3IF_MASK; // Clear the OC3 interrupt flag
}
void compare4_umeFunc(){   
    IFS0CLR= _IFS0_OC4IF_MASK; // Clear the OC4 interrupt flag
}

//  Timer4 の割り込みから呼びだされるサンプル関数---------------------------------
void timer4_sample()//デファオルと0.05ミリ秒
{
    static int count=0;
    if(++count == 10000){//0.5秒ごと
        _RB15 = ! _RB15;//点滅周期:1秒.
        count = 0;
    }
}

//  Timer5 の割り込みから呼びだされるサンプル関数---------------------------------
void timer5_sample()//デファオルと0.05ミリ秒
{
    static int count=0;
    if(++count == 10000){//0.5秒ごと
        _RB15 = ! _RB15;//点滅周期:1秒.
        count = 0;
    }
}

/*******************************************************************************
 * 
 *   割込みの初期化関数
 * 
 ******************************************************************************/

// コアタイマーサンプル用初期化---------------------------------------------------
void init_core_timer_1(){
    _CP0_SET_COUNT(0);//コアタイマを0にセット(CP0の9番レジスタ)
    _CP0_SET_COMPARE(_UM_CP0_SET_COMPARE);// コンペアレジスタに値設定(コアタイマがそれに達すると割り込み)  
    _CP0_BIC_DEBUG(_CP0_DEBUG_COUNTDM_MASK);// halt core timer and program at a debug breakpoint
    IFS0CLR = _IFS0_CTIF_MASK;// clear core timer interrupt flag
    IPC0SET = (7 << _IPC0_CTIP_POSITION);// set core time interrupt priority of 7
    IPC0SET = (3 << _IPC0_CTIS_POSITION);// set core time interrupt subpriority of 0
    IEC0CLR = _IEC0_CTIE_MASK;
    IEC0SET = (1 << _IEC0_CTIE_POSITION);// enable core timer interrupt
        
   	IEC0CLR = _IEC0_CTIE_MASK;// disable interrupt
    IEC0SET = _IEC0_CTIE_MASK;	// Enable(割込み許可)
}

// Timer1 の初期化 -----デフォルトで音符の長さ指定に使用---------------------------
void init_timer_1(){
    T1CON =0x00000000;//typeA,16bit, [1:1プリスケール
    TMR1=0x00000000; //16bitタイマの設定値(レジスタがカウントアップ)
    PR1=20000-1; // 0.0005 = 200000*(1/40e6) -1これは約0.5ミリ秒
    IPC1SET = 0x0000000C; // Set priority level = 3
    IPC1SET = 0x00000001; // Set sub-priority level = 1
    IFS0CLR = 0x00000010; // Clear the timer interrupt status flag
    IEC0SET = 0x00000010;//T1IE Timer1 Enable(割込み許可)
    //T1CONSET =0x8000; // Start timer1
}

// Timer2 の初期化 ------デフォルトでPWMのタイミングカウンターに使用----------------
void init_timer_2(){
    T2CONbits.ON = 0;// typeBでON
    T2CONbits.SIDL = 0;// デバイスがアイドルモードに移行しても動作を継続する
    T2CONbits.TGATE = 0;// ゲート時間積算を無効にする
    T2CONbits.TCKPS = 0;// タイマ入力クロック [1:1]プリスケール値
                            // TCKPS 3bit:111
    T2CONbits.T32 = 0;//TMRxとTMRyは別々の16ビットタイマを構成する
    T2CONbits.TCS = 0;//内部の周辺モジュール用クロック
    T2CON =0x00000000;//typeB,16bit, [1:1]プリスケール   
    //T2CON =0x00000070;//typeB,16bit, [1:256]プリスケール
    TMR2=0x0000; //16bitタイマの設定値(レジスタがカウントアップ)
    PR2=0x0FFFF; //16bit周期レジスタビット設定
    IPC2SET = 0x0000000C; // Set priority level = 3
    IPC2SET = 0x00000001; // Set sub-priority level = 1
    IFS0CLR = 0x00000200; // Clear the timer interrupt status flag
    IEC0SET = 0x00000200;//T2IE Timer2 Enable(割込み許可)
    //T2CONSET =0x8000; // Start timer2
}

//モータ用パルス幅変調モードの初期設定(PWM の設定)
void init_compare()// IDX_INIT_PWD
{
    //CN6(左側)前方向デューティ比用Output Compare Output5 の設定
    RPB2Rbits.RPB2R = 0x6; // RB2をOC5の出力にする。
    OC5CONbits.SIDL = 0; // アイドルモード中も動作を継続する
    OC5CONbits.OC32 = 0; //OCxR<15:0> およびOCxRS<15:0> を使って16 ビットタイマ源と比較する
    OC5CONbits.OCTSEL = 0; // Timer2 をこの出力コンペア モジュールのクロック源として使う
    OC5CONbits.OCM = 6; // OC1 をPWM モードにし、フォルトピンを無効にする
    IPC5bits.OC5IP = 5;// Set OC1 interrupt priority to 5
    IPC5bits.OC5IS = 2;// Set Subpriority to 3, maximum
    IFS0CLR= _IFS0_OC5IF_MASK; // Clear the OC5 interrupt flag
    //IEC0SET= _IEC0_OC5IE_MASK; // Enable Interrupt
            
    //CN6(左側)後ろ方向デューティ比用Output Compare Output1 の設定
    RPB3Rbits.RPB3R = 0x5; // RB3をOC1の出力にする
    OC1CONbits.SIDL = 0; // アイドルモード中も動作を継続する
    OC1CONbits.OC32 = 0; //OCxR<15:0> およびOCxRS<15:0> を使って16 ビットタイマ源と比較する
    OC1CONbits.OCTSEL = 0; // Timer2 をこの出力コンペア モジュールのクロック源として使う
    OC1CONbits.OCM = 6; // OC1 をPWM モードにし、フォルトピンを無効にする
    IPC1bits.OC1IP = 5;// Set OC1 interrupt priority to 5
    IPC1bits.OC1IS = 2;// Set Subpriority to 3, maximum
    IFS0CLR= _IFS0_OC1IF_MASK; // Clear the OC1 interrupt 
    //IEC0SET= _IEC0_OC1IE_MASK; // Enable Interrupt
    
    //CN7(右側)前方向デューティ比用Output Compare Output4 の設定
    RPB13Rbits.RPB13R = 0x5; // RB13をOC4の出力にする。
    OC4CONbits.SIDL = 0; // アイドルモード中も動作を継続する
    OC4CONbits.OC32 = 0; //OCxR<15:0> およびOCxRS<15:0> を使って16 ビットタイマ源と比較する
    OC4CONbits.OCTSEL = 0; // Timer2 をこの出力コンペア モジュールのクロック源として使う
    OC4CONbits.OCM = 6; // OC1 をPWM モードにし、フォルトピンを無効にする
    IPC4bits.OC4IP = 5;// Set OC1 interrupt priority to 5
    IPC4bits.OC4IS = 2;// Set Subpriority to 3, maximum
    IFS0CLR= _IFS0_OC3IF_MASK; // Clear the OC3 interrupt 
    //IEC0SET= _IEC0_OC3IE_MASK; // Enable Interrupt
    
    //CN7(右側)後ろ方向デューティ比用Output Compare Output3 の設定
    RPB14Rbits.RPB14R = 0x5; // RB14をOC3の出力にする。
    OC3CONbits.SIDL = 0; // アイドルモード中も動作を継続する
    OC3CONbits.OC32 = 0; //OCxR<15:0> およびOCxRS<15:0> を使って16 ビットタイマ源と比較する
    OC3CONbits.OCTSEL = 0; // Timer2 をこの出力コンペア モジュールのクロック源として使う
    OC3CONbits.OCM = 6; // OC1 をPWM モードにし、フォルトピンを無効にする
    IPC3bits.OC3IP = 5;// Set OC1 interrupt priority to 5
    IPC3bits.OC3IS = 2;// Set Subpriority to 3, maximum
    IFS0CLR= _IFS0_OC4IF_MASK; // Clear the OC4 interrupt flag
    //IEC0SET= _IEC0_OC4IE_MASK; // Enable Interrupt

    OC5R = 0;//_UME_CN6_OC5R;//0;//出力コンペアx コンペアレジスタ・・
    OC5RS = _UME_CN6_OC5RS;//出力コンペアx セカンダリコンペアレジスタ設定用(デューティー比 )
    OC1R = 0;//_UME_CN6_OC1R;//出力コンペアx コンペアレジスタ・・
    OC1RS = _UME_CN6_OC1RS;//出力コンペアx セカンダリコンペアレジスタ設定用(デューティー比 )
    OC4R = 0;//_UME_CN7_OC4R;//0;//出力コンペアx コンペアレジスタ・・
    OC4RS = _UME_CN7_OC4RS;//出力コンペアx セカンダリコンペアレジスタ設定用(デューティー比 )
    OC3R = 0;//_UME_CN7_OC3R;//0;//出力コンペアx コンペアレジスタ・・
    OC3RS = _UME_CN7_OC3RS;//出力コンペアx セカンダリコンペアレジスタ設定用(デューティー比 )
    
    //各出力コンペア モジュールを有効にする
    OC5CONbits.ON = 1; // RB2のOC5の出力をON(CN6の前方向)
    OC1CONbits.ON = 1; // RB3のOC1の出力をON(CN6の後ろ方向)
    OC4CONbits.ON = 1; // RB13のOC4の出力をON(CN7の前方向)
    OC3CONbits.ON = 1; // RB14のOC3の出力をON(CN7の後ろ方向)
}

// 現在未使用( PWM を使わないでモータを前進させる初期化)
void init_not_compare(){
    // ビット操作命令をポートに対して行う場合、ポートから全ての bit を読み出し、
    // 指定のビットをセットしてから、ポートに書き戻す。
    // その直後にビット操作命令がきた場合、ポートに書き戻したデータが確定しない
    // まま読み出しが起こり、ビットが反転する可能性がある。よって間にNOPを追加する。
    OC5CONbits.ON = 0; // RB2のOC5の出力をON(CN6)
    OC1CONbits.ON = 0; // RB3のOC1の出力をON(CN6)
    OC4CONbits.ON = 0; // RB13のOC4の出力をON(CN7)
    OC3CONbits.ON = 0; // RB14のOC3の出力をON(CN7)
    _RB2 = 0;// CN6 1-2
    __asm__("NOP");
    _RB3 = 0;// CN6 3-4 
    asm("NOP");
    _RB14 = 0;// CN7 1-2
    asm("NOP");
    _RB13 = 0;// CN7 3-4
    // 上記でNOPをなくすと、上記は動作しなかった。
    // 上記は、下記のように作る方が良い。
    PORTBCLR = 0x600c;//0b0110 0000 0000 1100;  
    //PORTBSET = 0x2004;//0b0010 0000 0000 0100;  
}




// Timer4,5 の初期化 -------------------------------------------------------------
void init_timer_4_5(){
    // ---- Timer4を使う指定 ここから
    T4CON =0x00000000;//typeB,16bit, [1:1]プリスケール
    TMR4=0x00000000; //16bitタイマの設定値(レジスタがカウントアップ)
    PR4=1999; // =0.0005/(1/40e6)-1 これは0.05ミリ秒
    IPC4bits.T4IP = 6; // Set priority level = 6(2番に大きな優先度)
    IPC4bits.T4IS = 0;// Set sub-priority level = 3(最大値)
    IFS0bits.T4IF = 0;// Clear the timer interrupt status flag
    IEC0bits.T4IE = 1;// Timer4 Enable(割込み許可)
    //T4CONbits.ON = 1;// Start timer4
    // ---- Timer4を使う指定 ここまで
    
    // ---- Timer5を使う指定 ここから
    T5CON =0x00000000;//typeB,16bit, [1:1]プリスケール
    TMR5=0x00000000; //16bitタイマの設定値(レジスタがカウントアップ)
    PR5=2000-1; // =0.0005/(1/40e6) -1これは約0.05ミリ秒
    IPC5bits.T5IP = 1; // Set priority level = 1(最小値)
    IPC5bits.T5IS = 3;// Set sub-priority level = 0(最小値)
    IFS0bits.T5IF = 0;// Clear the timer interrupt status flag
    IEC0bits.T5IE = 1;// Timer5 Enable(割込み許可)
    //T5CONbits.ON = 1;// Start timer5
    // ---- Timer5を使う指定 ここまで
}

// CN6 CN7 をPWMモードで使うかの切り替え
void set_pwd_mode(int flag){
    if(flag){
        handlers[_IDX_INIT_COMPARE] = init_compare; // PWM 関連の初期化
        
    } else {
        handlers[_IDX_INIT_COMPARE] = init_not_compare;// PWM を使わない設定
        
    }
    handlers[_IDX_INIT_COMPARE]();
}

/* =============================================================================
 * 割り込みハンドラなどの初期化ルーチンをまとめた関数
 * main()関数内のループ直前で呼ばれる。(SYS_Initialize ( NULL );の後で呼ばれる。))
 */
void init_interrupt()
{ 
    //コアタイマに関する初期化 init_core_timer_1();のような処理が登録が実行される。
    handlers[_IDX_INIT_CORE_TIMER]();
    
    // Timer1 初期化 
    handlers[_IDX_INIT_TIMER_1]();

    // Timer2 初期化 PWD の周期設定
    handlers[_IDX_INIT_TIMER_2]();// init_timer_2();
    
    // モータなどで使うPWMなど Output Compare Outputの初期化 
    _init_compare(); //handlers[_IDX_INIT_COMPARE]();

    // Timer3、ADC 初期化 
    handlers[_IDX_INIT_ADC_1]();
    handlers[_IDX_INIT_TIMER_3]();

    // Timer4,5 初期化 
    handlers[_IDX_INIT_TIMER_4_5]();
 
    // UART1 の設定init_uart()
    handlers[_IDX_INIT_UART1]();
    
    _RB9 = 0; // RTS(Request to Send (送信要求) ) の出力端子
    asm("nop");

    _RB8 = 0; // CTS(Clear to Send (送信可) ) の入力端子
    asm("nop");
    
    // 以下を1にすると、スルーモードで起動する。
    _UME_THROUGH_MODE = 0;
    
    //_UME_THROUGH_MODE = 1;// 実験の為スルーモード指定
    //(ESP32-WROOM-32D取り付け時,上記設定でSW2を押す操作を押さないと、Basicが起動  )
    
    // PB2にクロックを出力させて、周波数測定する時の設定
    // RPB2Rbits.RPB2R=0x07;// PB2を REFCLKO (50000Hz)に、ピン割り当てする。
    // REFOCONbits.OE = 1;  // REFERENCE OSCILLATOR CONTROL REGISTER

    if( power_on_flag == 1){//追加[2023-4]
        power_on_start();//追加[2023-4]
    }
    else //追加[2023-4]-----以下から
    {   // パワーオンでない場合(リセット)で実行する関数
        void (* func)(void) = (void *) 0x9D020000;
        if( *((uint32_t *)func) != 0xffffffff ){// EEPROMの記憶内容が0xffでない?
            func();
        }
    }   //追加[2023-4]-----以上までから

     //UMEHOSHI ITA アプリ用「初期ルーチン」デフォルトでは dummy_init_function関数 
    _init_sub_func(); //  handlers[_IDX_INIT_SUB_FUNC]の実行
    
} // end of void init_interrupt()
// main()関数内のループ直前で呼ばれる。(SYS_Initialize ( NULL );の後で呼ばれる。))


/* =============================================================================
 * 割り込みハンドラ
 * =============================================================================
/*
 *  優先度が同じで副優先度がより高い割り込みが発生しても、
 * サービス中の副優先度の低い割り込みは保留されません。
 * しかし、同じ優先度を持つ2つの割り込みが保留中である場合、
 * 副優先度が高い方の割り込みが先に処理されます
 */
// ------ コアタイマの割込みベクタの定義
// (下記のIPL7SOFTが優先度で、このソースでは、「IPC0SET」の設定と連動が必要な設定)
void __ISR(_CORE_TIMER_VECTOR, IPL7SOFT) CTInterruptHandler(void)
{   // システムクロック2つで、1カウントするカウンターが使われる。
    handlers[_IDX_CORE_TIMER_FUNC](); // デフォルトは440Hzのビープスイッチング
}

void __ISR(_TIMER_1_VECTOR,IPL3SOFT)Timer1Handler(void)
{
    handlers[_IDX_TIMER_1_FUNC](); // 音符長制御 
}

void __ISR(_TIMER_2_VECTOR,IPL3SOFT)Timer2Handler(void)
{
    //UMEHOSHI ITA アプリ用Timer2ルーチン デフォルトでは dummy関数がセット
    handlers[_IDX_TIMER_2_FUNC]();
}

// RB5 CN6[1-2]
void __ISR(_OUTPUT_COMPARE_5_VECTOR, IPL5SOFT) OC5_IntHandler (void)
{
    // コンペア割り込み OC5用
    handlers[_IDX_COMPARE_5_FUNC]();
}

// RB3 CN6[3-4]
void __ISR(_OUTPUT_COMPARE_1_VECTOR, IPL5SOFT) OC1_IntHandler (void)
{
    handlers[_IDX_COMPARE_1_FUNC]();
}

// RB14 CN7[1-2]
void __ISR(_OUTPUT_COMPARE_3_VECTOR, IPL5SOFT) OC3_IntHandler (void)
{
    handlers[_IDX_COMPARE_3_FUNC]();
}

// RB13[3-4]
void __ISR(_OUTPUT_COMPARE_4_VECTOR, IPL5SOFT) OC4_IntHandler (void)
{
    handlers[_IDX_COMPARE_4_FUNC]();    
}

void __ISR(_TIMER_3_VECTOR,IPL6SOFT)Timer3Handler(void)
{
   ((void (*)(struct ADC_BUFF*))handlers[_IDX_TIMER_3_FUNC])(p_buff);
}

void __ISR(_ADC_VECTOR,IPL7SOFT)ADC1Handler(void)
{
    ((void (*)(struct ADC_BUFF*))handlers[_IDX_ADC_1_FUNC])( p_buff );
}

void __ISR(_TIMER_4_VECTOR, IPL6SOFT) Timer4Handler(void)
{
    IFS0bits.T4IF = 0; // Clear the OC4 interrupt flag(この設定は次の割込みを可能にする).
    handlers[_IDX_TIMER_4_FUNC](); //timer4_sample()//デファオルと0.05ミリ秒
}

void __ISR(_TIMER_5_VECTOR, IPL1SOFT) Timer5Handler(void)
{
    IFS0bits.T5IF = 0; // Clear the OC5 interrupt flag(この設定は次の割込みを可能にする)
    handlers[_IDX_TIMER_5_FUNC](); // timer5_sample()//デファオルと0.05ミリ秒
}
// _TIMER_45_VECTOR と_TIMER_5_VECTOR は同じ20の番号になっているので、下記を定義するとエラー
//void __ISR(_TIMER_45_VECTOR, IPL7SOFT) Timer45Handler(void)
//{
//    IFS0bits.T5IF = 0; // Clear the OC5 interrupt flag(この設定は次の割込みを可能にする)
//    handlers[_IDX_TIMER_5_FUNC](); // timer5_sample()//デファオルと0.05ミリ秒
//}


/* =============================================================================
 * 起動時(リセット)直後に実行する。
 * ウメ・エディット・プログラムを実現するハンドラの初期化
 * 各種インターフェイス用記憶域、割込みテーブルの初期化
 * =============================================================================
 */

//void init_handlers (){//以前
void init_handle_area ()
{
    __RCONbits_t *rcon = (__RCONbits_t*) & RCON;//RCON: リセット制御レジスタ
    
    uint32_t t32 = (uint32_t) handlers;// 0xA0004000が記憶
    temp = sizeof(handlers[0]);//4が記憶
    temp = sizeof(handlers);//4が記憶
    t32  = (uint32_t) ram_area1;// 0xA0005000が記憶
    temp = sizeof(ram_area1);//0x3000がセット
    ram_area1[sizeof(ram_area1)-1]=0;//←これを行わないと、ram_area1領域ができない。
    ram_area2[sizeof(ram_area2)-1]=0;
    ram_area3[sizeof(ram_area3)-1]=0;
    
    led_D1 = 0; // D1 LED の初期点灯の予約

    // EEPROM操作関連 追加[2023-4]
    handlers[_IDX_NVM_ERASE_PAGE]=(void *)NVM_erase_page;
    handlers[_IDX_NVM_WRITE_WORD]=(void *)NVM_write_word;

    extern int reply_boot_message_status;
    reply_boot_message_status = 0;// :202503 追加

    // パワーONに関係なく初期化できる上記へ移動 :202503 
    core_once_count1_val = 880; // 0になるまでコアタイマでダウンカウント(1秒)
    core_once_count2_val = 1760; // 0になるまでコアタイマでダウンカウント(2秒)
    core_once_count3_val = 2640; // 0になるまでコアタイマでダウンカウント(3秒)
    core_once_count4_val = 3520; // 0になるまでコアタイマでダウンカウント(4秒)
                                // 上記4秒指定を追加:202503    
   
    if (_RB7 == 0 || rcon->POR == 1) {//パワーオン時(リセット無関係)処理======= 
        // SW2 (RB7)が押されている。または、パワーオン リセットが発生
        // (リセットだけでは実行しない処理)    
        // 起動時(リセット)直後でSW2を押すことでも実行。

        extern bool usb_recieved_flag;// :202503 追加( treuでUSBに送信可能状態)
        usb_recieved_flag = false;//一度でもUSBから受信があったら true

        // パワーONに関係なく初期化できる上記へ移動 :202503
        //core_once_count1_val = 880; // 0になるまでコアタイマでダウンカウント(1秒)
        //core_once_count2_val = 1760; // 0になるまでコアタイマでダウンカウント(2秒)
        //core_once_count3_val = 2640; // 0になるまでコアタイマでダウンカウント(3秒)
        //core_once_count4_val = 3520; // 0になるまでコアタイマでダウンカウント(4秒)
                                            
        // コア・タイマーの初期化    
        handlers[_IDX_INIT_CORE_TIMER] = init_core_timer_1;
        handlers[_IDX_CORE_TIMER_FUNC] = core_timer_umeFunc_1;//コア・タイマー処理
        _UM_CP0_SET_COMPARE = 22727u;//1/40e6*22727*2=0.00113635秒周期(440Hzブザー用)
        handlers[_IDX_CORE_TIMER_SUB_FUNC] = core_timer_sub_1;

        // スイッチ SW2 状態取得 ---------------------------------------------------
        handlers[_IDX_SWITCH2_STATE] = (void (*)(void) ) get_switch2_state;
        handlers[_IDX_CORE_WAIT] = (void (*)(void) ) core_wait;

        handlers[_IDX_EXTERNAL_0_VECTOR]= dummy_function; // INT0用 20240313追加
        handlers[_IDX_OUTPUT_COMPARE_2_VECTOR]= dummy_function; // OC20用 20240313追加

        extern void set_int_var(int specified_id, int value);
        handlers[_IDX_SET_INT_VAR]= (void *)set_int_var; // :202503 追加
        
        _UME_THROUGH_MODE = 0; // スルーモード 
        _UME_USB_CDC_DATE = 115200;//USB のボーレート
        
        // BEEP関連
        extern uint8_t my_beep_area[];
        _UM_PTR_BEEP_AREA = my_beep_area;
        _UM_PTR_GOTO_BEEP = my_beep_area;
        
        // Timer関連        
        handlers[_IDX_TIMER_1_FUNC] = timer1_umeFunc1_1;//TIMER1
        handlers[_IDX_INIT_TIMER_1] = init_timer_1;
        handlers[_IDX_TIMER_4_FUNC] = timer4_sample;
        handlers[_IDX_TIMER_5_FUNC] = timer5_sample;
        handlers[_IDX_INIT_TIMER_4_5] = init_timer_4_5;
        //_HANDLES[_IDX_INIT_TIMER_4_5] = init_timer_4_5;
        
        // compare関連
        handlers[_IDX_COMPARE_1_FUNC] =compare1_umeFunc;
        handlers[_IDX_COMPARE_3_FUNC] =compare3_umeFunc;
        handlers[_IDX_COMPARE_4_FUNC] =compare4_umeFunc;    
        handlers[_IDX_COMPARE_5_FUNC] =compare5_umeFunc;

        // PWM関連の初期設定 & Timer2
        //_UME_CN6_OC5R = 0;         
        _UME_CN6_OC5RS = 0;//0x0ffff;   // CN6 PWM 前方向へのデューティー比 
        //_UME_CN6_OC1R =0;
        _UME_CN6_OC1RS = 0;  // CN6 PWM 後ろ方向へのデューティー比 
        //_UME_CN7_OC4R = 0;
        _UME_CN7_OC4RS = 0;//0x0ffff;     // CN7 PWM 前方向へのデューティー比 
        //_UME_CN7_OC3R = 0;
        _UME_CN7_OC3RS = 0x00;     // CN7 PWM 前方向へのデューティー比 
        handlers[_IDX_TIMER_2_FUNC] =  timer2_umeFunc1_1;
        handlers[_IDX_INIT_TIMER_2] = init_timer_2;
        handlers[_IDX_INIT_COMPARE] = init_not_compare;// PWM を使わない設定
        //handlers[_IDX_INIT_COMPARE] = init_compare; // PWM 関連の初期化

        _UME_CONFIG = 0x0006; // BEEP デフォルトON, エラーBEEP通知ON
        
        // ADC関連 & Timer3
        handlers[_IDX_ADC_1_FUNC] = adc_umeFunc1_1;
        handlers[_IDX_INIT_ADC_1] = init_adc;
        handlers[_IDX_TIMER_3_FUNC] =  (void *)adc_usb_out;
        handlers[_IDX_INIT_TIMER_3] = init_timer_3;
        handlers[_IDX_ENCODE_ADC_BUFF] = (void *)encode_adc_buff;
        
        // UART1 関連 
        handlers[_IDX_INIT_UART1] = init_uart;
        handlers[_IDX_RECV_UART1] = (void *)recv_uart1;
        handlers[_IDX_SEND_UART1] = (void *)send_uart1;
        handlers[_IDX_MY_APP_TASKS] = (void *)My_APP_Tasks;
        handlers[_IDX_DEF_POLLS_UART] = (void *)recive_and_send_uart_with_polling;
        handlers[_IDX_CMD_POLLS_UART] = (void *)uart_cmd_mode_polling;
        handlers[_IDX_ISR_POLLS_UART] = (void *)uart_isr_buff_polling;
        
        // この関数内の最後で実行する「_handls_user_set_func()」の初期化
        handlers[_IDX_HANDLE_USER_SET_FUNC] = dummy_function;//何もしない

        extern int reply_boot_message();// :202503追加
        handlers[_IDX_REPLY_BOOT_MESSAGE]= (void *)reply_boot_message;
        
        //ウメ・エディットプログラムの初期化(_init_sub_func();の実行)
        handlers[_IDX_INIT_SUB_FUNC] = dummy_init_function;

        // USBからの置き換え可能な受信処理--------------------------------------------
        _RECIVE_USB_FUNC = dummy_recive;

        // ADC関連 -----------------------------------------------------------------
        handlers[_IDX_GET_PTR_ADC_BUFF] = (void (*)(void) ) get_ptr_adc_buff;
        handlers[_IDX_SET_ADC_EXE] = (void (*)(void) ) set_adc_exe;
        handlers[_IDX_SET_ADC_MODE] = (void (*)(void) ) set_adc_mode; 

        // 以下は、「ウメ・エディットプログラム」での利用を可能にするためのマクロ     
        // USBを介した文字列出力関連 -------------------------------------------------
        handlers[_IDX_API_REQUEST_ACC_OUTBUFF] = (void (*)(void) ) request_acc_outbuff;
        handlers[_IDX_API_RELEASE_ACC_OUTBUFF] = (void (*)(void) ) release_acc_outbuff;
        handlers[_IDX_API_SEND_CHAR] = (void (*)(void) ) send_char;
        handlers[_IDX_API_SET_BREAK_BUFFER] = (void (*)(void) ) setBreakBuffer;    
        handlers[_IDX_API_SEND_STRING] = (void (*)(void) ) send_string;
        handlers[_IDX_API_SEND_HEX_LOW] = (void (*)(void) ) send_hex_low;
        handlers[_IDX_API_SEND_HEX_HI] = (void (*)(void) ) send_hex_hi;
        handlers[_IDX_API_SEND_DECIMAL] = (void (*)(void) ) send_decimal;
        handlers[_IDX_API_GET_CAPACITY] = (void (*)(void) ) get_capacity;
        handlers[_IDX_API_SEND_16BYTE] = (void (*)(void) ) send_16byte;
        handlers[_IDX_SEND_PADDING_UINT] = (void (*)(void) ) send_padding_uint;
        handlers[_IDX_SEND_FLOAT] = (void (*)(void) ) send_float;
        handlers[_IDX_SEND_EXPONENT] = (void (*)(void) ) send_exponent;
        handlers[_IDX_SEND_UME_ID] = (void (*)(void) ) send_ume_id;

        // UART1 関連 --------------------------------------------------------------
        handlers[_IDX_API_REQUEST_ACC_UARTBUFF] = (void (*)(void) ) request_acc_uartbuff;
        handlers[_IDX_API_RELEASE_ACC_UARTBUFF] = (void (*)(void) ) release_acc_uartbuff;
        handlers[_IDX_GET_UART_CAPACITY] = (void (*)(void) ) get_uart1_capacity;
        handlers[_IDX_SEND_STR_UART1] = (void (*)(void) ) send_string_to_uart1;

        // ブザー関連 --------------------------------------------------------------
        handlers[_IDX_SET_BEEP_PERIOD] = (void (*)(void) ) set_beep_period;
        void set_beep_sound_node(int , uint8_t ,uint8_t, uint8_t);
        handlers[_IDX_SET_BEEP_SOUND_NODE] = (void (*)(void) ) set_beep_sound_node;
        void set_switching_period(int period);
        handlers[_IDX_SET_SWITCHING_PERIOD] = (void (*)(void) ) set_switching_period;
        void set_beep_code(uint8_t );
        handlers[_IDX_SET_BEEP_CODE] = (void (*)(void) ) set_beep_code;
        void clear_beep_code();
        handlers[_IDX_CLEAR_BEEP_CODE] = (void (*)(void) ) clear_beep_code;
        handlers[_IDX_DEBUG_POINT] = (void (*)(void) ) debug_point;    
   
        // DEBUG 関連定義------------------------------------------------------------
        handlers[_IDX_DEBUG_COUNT]=(void (*)(void) ) debug_count;
        handlers[_IDX_DEBUG_HEX4]=(void (*)(void) ) debug_hex4;
        handlers[_IDX_DEBUG_HEX8]=(void (*)(void) ) debug_hex8;
        handlers[_IDX_DEBUG_HEX16]=(void (*)(void) ) debug_hex16;
        handlers[_IDX_DEBUG_HEX32]=(void (*)(void) ) debug_hex32;

        // -------------------------------------------------------------------------
        handlers[_IDX_SET_PWD_MODE]=(void (*)(void) ) set_pwd_mode; 

        rcon->POR = 0;
        //PORは、POWER ON 時に1になる。リセット時には1にならない。       
        // 上記を行った後、リセットでは上記を行わなないようにクリアする
        
        led_D1 = 1; // D1 LED の初期点灯の予約

        power_on_flag = 1;//追加[2023-4]

    }//パワーオン時(リセット無関係)処理==============================ここまで
    
    _handle_user_set_func();//ユーザのhandlers設定関数(デフォルトでled_D1により点灯)

}