UMEHOSHI ITA TOP PAGE    COMPUTER SHIEN LAB

UMEHOSHI IT 基板の使い方の詳細ページ


[UMEHOSHI IT] 基板のテスト用プログラム仕様

[UMEHOSHI ITA]の制御で使っているIC「PIC32MX270F256B-I/SO」のフラッシュメモリには、テスト用プログラムが書き込まれいています。
以降では、このプログラムを「テスト・ウメ・フラッシュ」と呼ぶことにして解説します。
「テスト・ウメ・フラッシュ」の起動は次の種類があります。

操作概要
「micro B」のメスを差し込んで、5v電源を供給することでパワーオンの状態になります。パワーオン時の初期化(D1 LEDが点灯)
パワーオンの状態で、SW1とSW2を押して、SW1を離してから2秒以内でSW2を離すパワーオン時の初期化(D1 LEDが点灯)
パワーオンの状態で、SW1だけを押して、離す
(SW1がリセット用のスイッチですが、すべて初期化するものではありません。)
リセット時の初期化(D1 LEDが消灯)
パワーオン時にSW2を押して、3秒以上4秒未満後にSW2を離す. または、
パワーオンの状態で、SW1とSW2を押して、SW1を離してから3秒以上4秒未満後にSW2を離す
(リセットのSW1とSW2を押し、SW1を離してLED1が消灯に変わるまでSW2を押し続けます。)
スルーモードへの初期化(D1 LEDが消灯)
パワーオン時にSW2を押して、4秒以上後にSW2を離す. または、
パワーオンの状態で、SW1とSW2を押して、SW1を離してから4秒以上後にSW2を離す
(SW1とSW2を押し、SW1を離してLED1が消灯から点灯に変わるまでSW2を押し続けます。)
UART1コマンドモードへの初期化
(D1 LEDが点灯)

● スルーモードとはUSBに送った情報がUARTに送られ、逆にUARTに送った情報はUSBに送られる状態です。
  (フロー制御でなく、片方向モードで通信します。)
● UART1コマンドモードは、UARTで下記で示す「UME専用Hexコマンド」を受け付ける状態です。
 (UART1コマンドモードでは、USBで「UME専用Hexコマンド」を受け付けることも可能です。
  UART1コマンドモードでUARTに送れる「UME専用Hexコマンド」は、'S'と'R'と'G'から始まる命令だけです。
  そして、応答文字列は USBとUARTの両方に出力します。
  また、UART1との通信はフロー制御をしています。

「テスト・ウメ・フラッシュ」を利用したユーザー用のプログラムを 「ウメ・エディットプログラム」と呼ぶことにします。
この「ウメ・エディットプログラム」で利用可能なマクロや制御方法を以下で紹介しています。(詳細はリンク先です)

この「ウメ・エディットプログラム」で利用するRAMメモリは次のように大きく2つ領域に定義され、 利用できる領域は決められています。

この2つの領域の使い方を以下で解説しています。


「_HANDLES」(command.hで定義)のポインタを先頭する領域

この領域は、割り込みルーチン関連やシステム情報とこれに関連する関数などを記憶するテーブルの領域で、次ように定義されています。
void (*handlers_table[(0x1000>>2)-4])(void) __attribute__ (( persistent, address(_PTR_HANDLERS) )); 
// _PTR_HANDLERSは0x80004000(または0xA0004000)で、この位置から(0x1000>>2)-4=1020ワードの領域

この記憶域は、メインのループが始まる前に所定の内容に設定されます。(init_mainのinit_handle_area関数)
この領域の一部は、SW1のリセット操作で変更されない部分があります
Timer4に関する具体的な例として説明します。
パワーON時の初期で_HANDLES[_IDX_INIT_TIMER_4_5]にタイマ割り込みの初期化関数が記憶され、0.05m秒のインターバル割り込みの初期化がなされています。
そして、このタイマー割り込み関数から_HANDLES[_IDX_TIMER_4_FUNC]に記憶される関数がよびだされるようになっています。
そして_HANDLES[_IDX_TIMER_4_FUNC]にはパワーON時の初期設定で、1秒ごとにLED2を点滅する関数が記憶されています。
よって、利用者は「T4CONbits.ON = 1;// timer4の使用のオン」と 「IEC0bits.T4IE = 1;// Timer4 Enable(割込み許可)」を 実行するだけでLED2の点滅が可能になります。
そして、_HANDLES[_IDX_TIMER_4_FUNC]の内容を自身が作った関数に変更することで 希望の処理を0.05m秒ごとに実行できるようになります。
(この_HANDLES[_IDX_TIMER_4_FUNC]の記憶内容と「後述のプログラム領域」は リセットの初期化をしないので、 リセット後も動作できるようにな使い方が可能です。)
この仕組みでデフォルトの初期化関数や、各種割り込み関数を利用者が作った関数に登録し直すことで大きなシステム変更が可能になっています。
この変更を伴うプログラミングは少し難易度が高いのですが、電源を切ってしまえばもとに戻るので試して理解するのが一番です。
詳細は、こちらにまとめました。


利用者のプログラム領域

利用者がこのシステムを利用してプログラムする場合、次の領域を使います。この領域はSW1のリセット操作で変更されません
(リセット前に記憶した内容で動作を続けるプログラムが可能です。)

char ram_area1[0x3000] __attribute__ (( persistent, address(_PTR_RAM_AREA1) ));// PROGRAM AREA   (_PTR_RAM_AREA1 が 0xA0005000 )
char ram_area2[0x1000] __attribute__ (( persistent, address(_PTR_RAM_AREA2) ));// DATA AREA      (_PTR_RAM_AREA2 が 0xA0008000 )
char ram_area3[0x0F00] __attribute__ (( persistent, address(_PTR_RAM_AREA3) ));// USER INDEX AREA(_PTR_RAM_AREA3 が 0xA0009000 )

これらの記憶域はそれぞれ次の用途で使うことを想定しています。
ram_area1の「0x3000 byte」プログラム用(12288byte)先頭アドレス:0x80005000(0xA0005000)
ram_area2の「0x1000 byte」変数などのデータ用(4096byte)先頭アドレス:0x80008000(0xA0008000)
ram_area3の「0x0F00 byte」絶対アドレス指定で利用する記憶域(3840byte)先頭アドレス:0x80009000(0xA0009000)

この記憶域は、USB(CDC)を介した通信で、RAMメモリの書き込み、指定アドレスの実行、RAMメモリの内容取得 などのコマンド操作ができます。
この書き込み命令でプログラムを転送し、絶対アドレス指定の実行命令でプログラムを起動する仕組みです。

[UMEHOSHI ITA]の初期化は2段階あり、パワーオンON時の初期化というものがあり、 パワーオンON時はこの初期化の後に、リセットによる初期化が行われます。
リセットにより初期化は、スイッチ(SW1)を押すこと行われます。
このスイッチ(SW1)を押すリセット操作は、「ウメ・エディットプログラム」内容を初期化しません。
よって、スイッチ(SW1)リセット操作でRAMに記憶したプログラムを再起動させる芸当ができます。

なお、パワーオンON時の初期化は、デフォルトの使いい方をしている場合、次の操作で動かすことができます。
リセットスイッチ(SW1)と SW2を同時に押して、その後でSW1を離してから SW2を(1秒未満で)離します。
なお、デフォルトのプログラムでは、パワーオンON時の初期化が行われるとLED1が点灯します。
リセットスイッチ(SW1)の操作だけの場合は、LED1が点灯しません。よってパワーオンONの直後か判定できます。

なお、SW1と SW2を同時に押して、その後でSW1を離してから SW2を(1秒未満で)離します。
( デフォルトのコアタイマに登録される core_timer_sub_1関数 で処理しています。)

送受信は基本的に16進を表す文字列で、次のように決められています。一つのコマンドは[CRLF]の改行の送信で終結します。
つまり、1行が1コマンドとなります。そして仕様に合わない文字列の文字列の受信は無視されます。
これを記憶したファイルを「UME専用Hexファイル」を呼ぶことにしています。
このUME専用Hexファイルは、「umehoshiEdit」という開発ツールを使います。 「umehoshiEdit」の開発環境は、 こちらを参考に用意してください

「UME専用Hexコマンド」

データ書き込み命令'S' 文字列の仕様
プログラム・データなどのコードなどを転送する ['S'レコード種別文字] [2文字の個数データ] [アドレス16進8文字] [2文字レコード種別] 『[16進連続2文字]が(データ長)分並ぶ」』 [2文字チェックサム]
[80008000] 番地に16byteをセットする例 S108000800000000102030405060708090A0B0C0D0000E5の改行でこの構成は次のようになる。
[S] [10] [80008000] [00] [00] [01] [02] [03] [04] [05] [06] [07] [08] [09] [0A] [0B] [0C] [0D] [00] [00] [E5]
[S]〜 チェックサムの[E5]の手前まで文字コードの総和は0x091Bになり、これにチェックサム0x0E5と加算すると0xA00になり、1byteでは00になる。
[アドレス16進8文字] の設定部が、0x80000000 以上で 0x8000ffff 以下、又は 0xa0000000 以上で 0xa000ffff 以下であれば、RAMとして設定
そして、0x9D020000 以上で 0x9D03FFFC 以下時は、ROMとして書き込み処理を行います。
上記の応答 設定したスタートアドレスを設定後に出力する文字列。 例「SET:80008000
(設定が失敗した場合、設定対象がRAMの場合はこの応答文字例を出しません。ROMの場合は、エラー文字列を出します。)
実行呼び出し命令'R' 文字列の仕様
指定アドレスの関数を呼び出す ['R'レコード種別文字] [00の2文字] [アドレス16進8文字] [00の2文字] [2文字チェックサム]
[80005000]番地の関数を実行 R00800050000061の改行でこの構成は次のようになる。
[R] [00] [80005000] [00] [61]
上記の応答 例「START:80005000」のメッセージ後に、この位置の関数を呼び出しします。
データ取得命令'G' 文字列の仕様
メモリ情報の取得 ['G'レコード種別文字] [2文字の個数データ] [アドレス16進8文字] [00の2文字] [2文字のチェックサム]
[80009000]番地から16byteのメモリ内容の取得 G10800090000067の改行でこの構成は次のようになる。
[G] [10] [80009000] [00] [67]
上記の応答 このレスポンスは、':'を先頭にしたフォーマットで応答する。次の形式である。
[:] [データ長の16進2文字] [アドレス16進8文字] [00の2文字] [データ長の16進2文字の連続] [2文字のチェックサム]
例 「:108000900000EE0ABC6EC71A6C232B1CA4A3A13D2CAAFE
上記は、次の構成である。 [:][10][80009000][00][EE][0A][BC][6E][C7][1A][6C][23][2B][1C][A4][A3][A1][3D][2C][AA] [FE]
【エコーモード】切り替え命令
直前が改行である時、Eと改行("\r\n")を送ると切り替わわります。(チェックサム不要)
上記の応答パワーONの直後はエコーモードがONで、ONの時はUSB送った情報がそのままUSBに戻されます。
ONモードの時にEと改行("\r\n")を送ると、ECHO OFFが表示されてOFFモードになります。
OFFモードのの時にEと改行("\r\n")を送ると、ECHO ONが表示されてONモードになります。
【 一時スルーモード】切り替え命令
直前が改行である時、Tと改行("\r\n")を送ると【 一時スルーモード】になります。(チェックサム不要)
また直前が改行である時、「code from through mode to nomal mode 123」と改行を送ると、 【 一時スルーモード】から【通常モード】に戻ります。
上記の応答【 一時スルーモード】になると、USBに送った情報がUARTに送られ、逆にUARTに送った情報はUSBに送られるようになります。
この状態では UARTに接続したデバイス(例えば、U17に取り付けたRN4020、またはU19に取り付けたESP32、またはCN11-12に取り付けたRN42など)とUSBを介した 通信が可能な状態です。
なお、この【 一時スルーモード】は【通常モード】に戻れますが、起動時に3秒以上4秒未満のタイミングでSW2を押した時に遷移するスルーモードは【通常モード】に戻ることができません。

「umehoshiEdit」開発ツールでは、上記で示したコマンド通信を利用してプログラミングを転送しています。
それ以外に「Tera Term」のようなターミナルエミュレータを別途にインストールして確認することもできます。
以下で、「Tera Term」を使って動作を確認する例を示します。
まずUSBケーブルで、[UMEHOSHI ITA]とPCを接続して、「Tera Term」を起動します。
PC側で起動した「Tera Term」において、 以下のように接続した時に出現するUSBのCOMポートをの設定をします。(この例ではCM3を選んでいます。)
この操作は、「Setup」メニューの「Serial Port」メニューで行います。


同様に「Setup」メニューの「Tertminal」メニューで、改行(New-line)でReceive:とTranmit:を「CR+LF]にします。

以上で、ターミナルで入力した文字列がUSBを介して、「UMEHOSHI ITA」に送られるようになります。
適当な文字列(hello)を入力して[Enter]してみましょう。
これで表示さるということは、入力した文字列が「UMEHOSHI ITA」へ送られて、 その応答として、エコー(echo)となる同じ文字が「UMEHOSHI ITA」から戻ってきて表示しているのです。
このEchoモードをOFFすると、何も表示しなくなります。
「UMEHOSHI ITA」は[E\r\n]を受信することで、EchoのON/OFFの切り替えができます。
(この時、モードが切り替わったことを知らせるメッセージが出ます)
以下では、『Eと[Enter]』のキー操作を2回行った後に『Tと[Enter]』の入力操作をしています。
そして、最後に「G10800090000067」を入力して[80009000]番地から16byteのメモリ内容を表示しいている例です。

hello
E
ECHO OFF
ECHO ON
G10800090000067
::10800090000051495AE359ED7A49E97DD297D964CA02F1
以上より分かるように、このターミナルでは、 「umehoshiEdit」開発ツールなどで作ったUME専用Hexの文字列をコピーし、ここに貼り付けることで、 「UMEHOSHI ITA」基板に対して、メモリへの設定や、希望アドレスからの実行の操作ができます。

[UMEHOSHI IT] の制御

以下で、command.hで定義される_HANDLESポインタを先頭する領域利用したマクロの意味を説明します。

スイッチの状態

マクロ解説
_switch2_state()戻り値が1であればSW2のスイッチを押している状態で、50回以上呼び出した状態です。
戻り値が0であればSW2のスイッチを離している状態で、50回以上呼び出した状態です。
(押された状態がこのマクロ呼び出しが50回以上を変動しない場合、戻り値は変化しません。)
単にSW2のスイッチ状態を調べるだけであればこのマクロでなく、「 (PORTB & 0x80) == 0」の判定を使うとよい。

リセット用のSW1と、任意用途のSW2が取り付けできます。
_HANDLES[_IDX_CORE_TIMER_FUNC] を変更していなければ、SW2の状態チェックの状態は、 任意のタイミングで_switch2_state() マクロで判断できます。 この戻り値が 1 であれば押されていると判断できます。 押されていない状態であれば 0 が戻り値です。
この値は、スイッチチャタリングを判定しないように、コアタイマ割り込みで 50サイクル分押し続けている場合に1なる判定をしています。
なお、この関数の戻り時間が遅延の時間を待つ訳ではなく、すぐにリターンする仕様になっています。
 (このサイクルの遅延は、デフォルトで(1/40e6*22727*2=0.00113635秒の割り込み周期*100=約0.1秒)後に状態が反映します。)
なおSW2は、リセットSW1を押して離した時の判定で押されていると、 通常リセットと異なるパワーON同等の初期化ルーチンが、デフォルトで呼び出しされるようになっています。
パワーON時の初期化は、SW1によるリセットと異なる初期化が含まれています)
また、リセット(SW1)と、SW2を同時に押して、SW1を離してからもSW2を3秒以上押し続けると、スルーモードという特別な モードへの遷移します。
また、リセット(SW1)と、SW2を同時に押して、SW1を離してからもSW2を4秒以上押し続けると、コマンドモードという特別な モードへの遷移します。

LEDの表示とその制御

D1,D2,D3の箇所にLEDが取り付けできます。(なおD3は,別途にジャンパ配線の半田付けをしないと制御できません。)
D1,D2,D3のそれぞれをを、LED1,LED2,LED3と呼んで説明します。
デフォルトでパワーONの時にLED1が点灯し、LED2が消灯します。
LED1は、リセットスイッチ(SW1)の操作だけでは点灯しません。 起動時のLED1は、パワーON時の初期化を行って時に点灯します。
リセット(SW1)と、SW2を同時に押して、SW1を離してからもSW2を押している場合も、 パワーON時の初期化が行われて点灯します。
そしてそのまま3秒以上のSW2を押し続けると消灯してスルーモードに遷移します。
(パワーON時にSW2を押し続けても同じで、LED1はパワーONのタイミングで点灯しますが、3秒後に 消灯して、スルーモードになります。)
そしてそのまま3秒以上(リセットやパワーONから4秒以上)のSW2を押し続けると、再び点灯してコマンドモードに遷移します。

これ以降におけるLED点灯・消灯操作は自由できます。(デフォルトで起動3秒以前行ったLED1プログラム操作は無効)
#include <xc.h>を行えば、下記ののように操作できます。(ビット操作の直後は何もしないnopを入れます)

点灯操作消灯操作備考
LED1PORTBSET = 0x8000; PORTBCLR = 0x8000;PORTB のbit15を1にすると点灯します。
このビットは_RB15マクロで参照や代入操作できます。しかし、 「ポートに対する特定のビット操作命令が連続する場合、後述命令を正しく実行できないケース」があるようです。
その場合、_RB15 = 1; asm("nop");のような回避策があるようですが、マクロ命令でなく、PORTBSET や PORTBCLR や PORTBINVの命令を 直接に使った方がよいでしょう。
LED2_RB5 = 1; asm("nop");_RB5 = 0; asm("nop"); PORTBのbit5の端子は、 同時にSP(圧電ブザー)、D4,D5(赤外線LED)制御用トランジスタに繋がていおり、連動します。
(なお点灯であれば、PORTBSET = 0x0020; で行うようなコードの方が良いでしょう)

なお、LED3は部品U17(RN4020のBLE)の8Pin(BLEの接続状態で点灯)に繋がっています。
U17を取り付けしていない状態で、 ジャンパ配線(JMP9)を半田付けすると「PIC32MX270F256B-I/SO」のRTS端子(_RB9)に繋がります。

CN6、CN7に接続するモータなどの制御

CN6、CN7の各は端子「H-Bridge Motor Drive」の回路構成になっています。
それにより、CN6[1-2pin]とCN6[3-4pin]の間やCN7[1-2pin]とCN6[3-4pin]に 正または負の電圧(DC-JACKの供給電圧Mv)を供給できます。
パワーON時の初期化ではPWM((Pulse Width Modulation)は使わないモードになっています
それにより、例えば RB2を1, RB3を0にするだけで、CN6の1-2ピンが3-4ピンよりMvの供給電圧分だけ高い電位になります。
(これによりCN6にモータなどを接続していれば駆動できます。)
これらを制御する命令と端子名の出力状態とコネクタの出力状態の関係を以下にまとめて示します。
下記の0vやMvの表現はロジック側の電位(3.3v)ではありません。DC-JACK供給側の電位です。

 CN6の制御 
設定コードRB3RB2CN6の[1-2pin] CN6の[3-4pin]CN6の[3-4]をベースとした[1-2]の電位
PORTBCLR = 0b0000000000001100;00MvMv0v
PORTBCLR = 0b0000000000001000;
PORTBSET = 0b0000000000000100;
01Mv0v+Mv
PORTBCLR = 0b0000000000000100;
PORTBSET = 0b0000000000001000;
100vMv-Mv
PORTBSET = 0b0000000000001100;110v0v0v

 CN7の制御 
設定コードRB14RB13CN7の[1-2pin]CN7の[3-4pin]CN7の[1-2]をベースとした[3-4]の電位
PORTBCLR = 0b0110000000000000;00MvMv0v
PORTBCLR = 0b0100000000000000;
PORTBSET = 0b0010000000000000;
010vMv+Mv
PORTBCLR = 0b0010000000000000;
PORTBSET = 0b0100000000000000;
10Mv0v-Mv
PORTBSET = 0b0110000000000000;110v0v0v

上記のような、ビットのクリアやセット命令で、希望のビットを0や1にすることで制御します。
なお、モータなどを付けた場合、Mv-Mvの電位になる所で 回転します。(0vの電位の行の設定時は動作しません。)
正転や逆転の状態はモータの接続状態で逆になります。



CN6、CN7のPWM(Pulse Width Modulation)制御

パワーON時の初期化ではPWM((Pulse Width Modulation)は使わない状態です。
使う場合は「_set_pwd_mode(1);」のマクロ実行と「T2CONbits.ON = 1;」のTimer2の機能ONで、PWMを使う状態にします。
PWMは、Timer2のコンペア モジュールを利用して動作しています。(参考)
内部の周辺モジュール用クロック(PBCLK:40MHz)をPR2=0x0FFFFの周期で使う分解能(1/40e6*0x10000=0.0016384秒)で 制御しています。
なおTimer2の割り込み(0.0016384秒周期)は、デフォルトで何もしない処理(IFS0CLR = 0x00000200だけ)なっています。

このモード設定関連のマクロを以下に示します。

マクロ表現動作説明
_init_compare() _HANDLES[_IDX_INIT_COMPARE]の関数へのポインタを実行するマクロです。(システムで使われ、一般に呼び出すことは少ないでしょう)
_HANDLES[_IDX_INIT_COMPARE]には、電源ONの初期時でPWMを使わない初期化関数がセットされます。 ( この電源ONの初期時は、OC5CONbits.ON,OC1CONbits.ON, OC4CONbits.ON, OC3CONbits.ON を0にすることで 各コンペア モジュールを無効にしています。)
リセットだけでは変化しません。下記_set_pwd_mode(f)で_HANDLES[_IDX_INIT_COMPARE]を変更することでモードを変更しています。
_set_pwd_mode(f)fを1で実行すると、PWM を使う初期化で、fを0で実行するとPWMを使わない初期化を行います。
この実行により、同時に _HANDLES[_IDX_INIT_COMPARE] も設定されます。それによりリセット後もモードが持続します。
fを1で実行すると、PWM を使う初期化設定をします。その内容は、 Timer2 をこの出力コンペア モジュールのクロック源として使うように 設定し、OC5CONbits.ON, OC1CONbits.ON, OC4CONbits.ON, OC3CONbits.ON を1にして各コンペア モジュールを有効にしています。
デフォルトの Timer2周期は、約0.0016秒ですが、起動時は機能が無効にしてあるので、 PWM を使う場合は、別途に「T2CONbits.ON = 1」の命令でTimer2の機能を有効にする必要があります。
このPWM を使う設定では、RB2、RB3、RB14、RB13の端子を1にするデューティ比を OC5RSOC1RSOC3RSOC4RSのレジスタ設定で行います。
その設定値は0〜0x0ffffの16ビットで、この設定比がデューティ比の0〜100%に対応します。

「_set_pwd_mode(1);」と「T2CONbits.ON = 1;」の実行でPWMが働く訳ですが RB2、RB3、RB14、RB13の対応する出力デューティ比100%にするレジスタの設定を下記にまとめます。 ()

 CN6の制御 
RB2のOC5RSRB3のOC1RSCN6の[3-4]をベースとした[1-2]の電位
0x0ffff0+Mv
00x0ffff-Mv

 CN7の制御 
RB14のOC3RSRB13のOC4RSCN7の[1-2]をベースとした[3-4]の電位
00x0ffff+Mv
0x0ffff0-Mv

上記OC5RSOC1RSOC3RSOC4RSの レジスタの設定は、PWMのデューティ比の設定で、(1〜0x0ffff)の範囲で行います。
(0x0ffffが最大出力で、0にすると、[1-2]と[3-4]の電位差はゼロになります。)
内部的には、OC5CON、OC1CON、OC3CON、OC4CONの出力コンペア制御レジスタの設定をパルス幅変調モードにして、 Timer2 をクロック源にして利用しています。
そしてそれぞれのこれらレジスタには対になるOC5ROC1ROC3ROC4Rレジスタがあるのですが、 実際にはこれがTMR2と比較されてデューティが決まります。 そして、TMR2(16bitタイマレジスタ)カウントアップして PR2(16bit周期レジスタ)が一致したタイミングで、 OC5RSOC1RSOC3RSOC4RSOC5ROC1ROC3ROC4Rにセットされて、次のデューティ比が決まります。

なお、OC5RSOC1RSOC3RSOC4RSの初期設定値は、
それぞれ _UME_CN6_OC5RS_UME_CN6_OC1RS_UME_CN7_OC4RS_UME_CN7_OC3RS のマクロ変数で設定されます。
(このマクロ変数はリセットで初期化されません。)


[UMEHOSHI IT] のサウンド制御、エラー通知

_RB5の端子に繋がるSP(圧電ブザー)で音を出します。(LED2や赤外線LEDと連動します)
音の周波数はコアタイマの割り込みで変更され、以下のマクロで制御できます。(各設定は、後述のデバック用ビープ関数にも影響し、両方を使うことはできません。)

マクロ表現動作説明
_UM_CP0_SET_COMPAREこのマクロ変数の初期値は22727uのラの音(440Hz)で、代入で音色が変わる。
(コアタイマ割り込み内で、割り込み周期変更に使う変数なので、下記関数群に大きく影響します。) 1/40e6がコアタイマの周期で、この設定による周波数は、1/(1/40e6*_UM_CP0_SET_COMPARE)で算出できます。
_set_beep_period(d)実行すると、引数で0より大きな数を指定した場合、その回数だけブザー端子を反転することで音を鳴らします。
反転周期は、コアタイマの周期を指定する_UM_CP0_SET_COMPAREで決まるので、音がが出る長さはこの設定に依存します。
なお引数に-1を指定すると、期間無しで永続的に鳴らします。
鳴っている途中で発音期間を変更できます。(0の指定で止まります)
_UM_PTR_BEEP_AREA後述の音の登録関数用の記憶域を管理するポインタで変更可能(初期の記憶域は[3*16+1+300]byte) この記憶域の要素はデータが存在する範囲を再生させるように使い、先頭にデータが無ければ再生しません。
_set_beep_sound_node(i,c,s,n)音の登録関数で、上記「_UM_PTR_BEEP_AREA」のi番目に、cの鍵盤番号で、sの長さの音と、nの長さの無音を登録します。
この関数は周期が0.5mS 周期でTimer1割り込みをONにして使う前提です。(set_switching_period(125)とします。)
この時、音の長さの引数は32分音符:0.0625秒を1とした指定になります。
(2なら16分音符、4なら8分音符、8なら4分音符(0.5秒)、16が2分音符、32が全音符)
iの引数が0の時、_UM_PTR_BEEP_AREAを記憶域に使う初期化が行われる。(このマクロ変数に自身で用意した記憶域を指定できる。
iの範囲は、この記憶域によるが、デフォルトでは0から99の音登録が可能です。
iが0の先頭要素のcの鍵盤番号が以外で音の生成が始まります(演奏が始まります)。
再生は、「_UM_PTR_BEEP_AREA」の登録データに従い順次に行われ、cの鍵盤番号が0の所で終わります。
デフォルトではループ状態で、最後の要素の音の次は先頭に戻って音を生成します。
この再生はTimer1の割り込みを許可(T1CONSET =0x8000;)する必要があります。
_set_beep_code(d) モールス信号のような音の登録関数で、上記「_UM_PTR_BEEP_AREA」の記憶域に登録します。
引数dの上位4ビットの1が長音、0が短音、下位4ビットは[CB:1][LN:3]で次の意味です。
[CBの1ビット]前のバイトに続く音の場合は1、前のバイトと音と離れる場合は0
[LNの3ビット]上位4ビットの音長を意味する1や0の有効なビット数
例 Gのコードであれば 「― ― -」音で、次のビット列となる。
         1100 0011
上位4ビット「1100」、CBが「0」、LNが「011」の3つの音を意味する。
なお、CBが「1」である時、これが続くバイトの範囲を繰り返します。
この関数を複数回使うことで、その登録順に音が再生されます。
また特別にdを0b11110000にすると、長い区切り用の無音登録で、dを0にするとそれ以降の登録ができなくなります。
デフォルトではループ状態で、最後の要素の音の次は先頭に戻って音を生成します。
_set_switching_period(d) 鳴っている途中で発音期間(テンポ)を変更できます。このテンポに相当する値はコアタイマの周期に依存します。
デフォルトは90で、50〜150程度使うのがよいでしょう。(小さいすぎや大きすぎると不具合が生じます)
_clear_beep_code() _set_beep_sound_node(i,c,s,n)や_set_beep_code(d) の内部情報を初期化して音を停止します。
(_RB5 = 0の実行でLED2も消灯します。)そして再び先頭の音から登録できる状態にします。
また後述するbebug_〜の関数やエラー音、エラー情報の復帰も行われます。
(なお、音が鳴っていない時の初期化は即座に実行されてリターンします。しかし音が鳴っている場合は、 初期化の予約だけ行われ、実際の初期化は音生成の割り込みと連動するためにリターンの時間がかかります。
その場合、割り込み周期の設定によっては、直後の音登録関数の実行ができないことがあります。)
_UM_PTR_GOTO_BEEP _set_beep_sound_node(i,c,s,n)や_set_beep_code(d)で登録した連続音は、 登録した音の生成後に、_UM_PTR_GOTO_BEEPのポインタの登録情報で再生する挙動になっています。
そして、デフォルトの_UM_PTR_GOTO_BEEPは_UM_PTR_BEEP_AREAと同じになっており、再生がループする仕組みになっています。
そして、_UM_PTR_GOTO_BEEPをNULLにすると、このループが働かなくなります。
つまり、単純に「_UM_PTR_GOTO_BEEP = NULL」とするとループ生成でなく単発的な登録音の再生状態になります。
_UME_CONFIGデフォルトで下位の1byte目が、0x06になっています。
0x01のビットが立っていれば音のON/OFFの制御を「D1」に反映します。
0x02のビットが立っていれば音のON/OFFの制御を「D2やブザーなど」に反映します。
0x04のビットが立っていれば、エラー通知音を音のON/OFFの制御に反映します。
つまり、エラー通知はデフォルトでONになっています。

なお、_set_beep_sound_node(i,c,s,n)関数と_set_beep_code(d)関数の両方を同時に使う作品はできません。
_set_beep_code(d)はコアタイマでタイミングを作っており、音の周波数と上げると音生成のテンポも速くなります。
_set_beep_sound_node(i,c,s,n)の音色はコアタイマで、テンポはTimer1の割り込み周期で変化します。(Timer1の割り込みを許可が必要)
上記どちらかを使うことで、内部の状態が変化して、音生成の開始と判断されます。
Timer1の割り込みを許可(T1CONSET =0x8000;)して、両方の登録関数を使うと、両方の動作を始めますが、 音のタイミングが重なるので、訳が分からない音が生成されるでしょう。

エラー通知について

デフォルトで次のブザー通知が行われます。なお圧電ブザー、D2:LED、赤外線LEDは繋がっているので連動します。
(・が短音、ーが長音です。プログラミングによってはエラー通知が出きない場合もあります。
先頭音パターン続く音の4パターン意味
・・・ー・・・・ ・・・・ ・・・・ ・・・ー  USBへの受信完了状態エラー
・・・ー・・・・ ・・・・ ・・・・ ・・ー・  USBへの送信完了状態エラー
・・・ー・・・・ ・・・・ ・・・・ ・ー・・  USBのシーケンスエラー
・・・ー・・・・ ・・・・ ・・・・ ー・・・  USBの予期しない状態エラー
・・ー・・・・・ ・・・・ ・・・・ ・・・ー  UARTパリティエラー判定
・・ー・・・・・ ・・・・ ・・・・ ・・ー・  UARTフレーミングエラー(STOPbit異常)
・・ー・・・・・ ・・・・ ・・・・ ・ー・・  USRT受信バッファオーバーラン エラー
・・ー・・・・・ ・・・・ ・・・・ ー・・・  予期していない送信割り込み
・・ー・・・・・ ・・・・ ・・・ー ・・・・  UART受信処理でバッファ処理失敗
・・ー・・・・・ ・・・・ ・・ー・ ・・・・  UART送信処理で送信バッファフルで設定失敗
・・ーー・・・・ ・・・・ ・・・・ ・・・ー  ADC取得データの送信が間に合わなないエラー
これらの通知は、後述の_debug_hex4やdebug_hex16を使って行われます。

[UMEHOSHI IT] デバックのブザー音制御

上記の_set_beep_code(d) 機能を利用して、デバック用に変数の内容を音で確認するためのデバック用関数を用意しています。
 (これは、_set_beep_code(0x0f0);のような無音の登録コードと併用して使うことも可能です)
また、内部のエラーの状態をビープ音で確認することもできます。
以下に関連マクロを示します。

マクロ表現動作説明
int _debug_count(n,c,b) bが1の時、nの識別番号で、cの回数実行後にnの4ビットパターンの音を登録します。
(よってnの指定範囲は0から15です)
nの識別番号で登録した音が登録されると、その番号での音の登録は出来なくなります。
bが1で音を登録した時や、それ以降のの戻り値は1になります。 この音の登録は上記で示すset_beep_code(d)関数で行われます。よって停止に _clear_beep_code() も使えます。
//使い方例
static int b0,b1,b2; 
b0=debug_count(0, 100, 1);//この命令を100回通過した時にb0がtrueで、0の4bit音登録
// ・・・・・・・・・・・・
b1=debug_count(1, 50, b0);//b0がtrueで、50回通過した時に、b1がtrueで、1の4bit音登録
// ・・・・・・・・・・・・
debug_count(2, 1, b1);//b1がtrueで、1回通過した時に、、2bitの4bitパターン音が登録
int _debug_hex4(n,c,b) bが1の時、nの識別番号で、cの下位4ビットの音を登録します。登録した順番で音を鳴らします。
nの識別番号で登録した音が登録されると、その番号での音の登録は出来なくなります。
bが1で音を登録した時や、それ以降のの戻り値は1になります。(それ以外は0を返す)
この音の登録は上記で示すset_beep_code(d)関数で行われます。よって停止に _clear_beep_code() も使えます。
int _debug_hex8(n,c,b) bが1の時、nの識別番号で、cの下位8ビットの音を登録します。登録した順番で音を鳴らします。
nの識別番号で登録した音が登録されると、その番号での音の登録は出来なくなります。
bが1で音を登録した時や、それ以降のの戻り値は1になります。(それ以外は0を返す)
int _debug_hex16(n,c,b) bが1の時、nの識別番号で、cの下位16ビットの音を登録します。登録した順番で音を鳴らします。
nの識別番号で登録した音が登録されると、その番号での音の登録は出来なくなります。
bが1で音を登録した時や、それ以降のの戻り値は1になります。(それ以外は0を返す)
int _debug_hex32(n,c,b) bが1の時、nの識別番号で、cの32ビットの音を登録します。登録した順番で音を鳴らします。
nの識別番号で登録した音が登録されると、その番号での音の登録は出来なくなります。
bが1で音を登録した時や、それ以降のの戻り値は1になります。(それ以外は0を返す)
	//上記の各種の使い方の例
	static int t0,t1,t2,t3,t4;
	t0=_debug_hex4(0,0x5,1);	// 0x5のの音パターンを、1のID番号で登録
	t1=_debug_hex4(1,0,t0);	// 上記が登録済みであれば、0の音パターンを1のID番号で登録	
	t2=_debug_hex8(1,2,t1);
	if(t2 && !t3) _set_beep_code(0x0f0); //無音
	t3=_debug_hex16(0,15,t2);
	t4=_debug_hex32(18,255,t3);
int _debug_point(n, c) nの番号順で予想通りの記述位置をcount回数動作しているか調べる関数
(nのビットパターンの音登録を、c回数の確認時に行っているが、内部ではdebug_countを利用して実現しています。 よって、debug_countを併用して使うと正しく動作できないことがあります。) nの識別番号は、0から、1、2、・・15と順番に指定して使い、途中で使わない番号があると、それ以降の番号を指定した箇所は機能しません。
	//上記の各種の使い方の例
	_debug_point(1, 1);// 0の音が登録済みの場合に、2回通過したら1のパターンの音を鳴らすように1の識別番号で登録
	・・・任意コード・・・	
	_debug_point(0, 2);// 2回通過したら0のパターンの音を鳴らすように0の識別番号で登録(ここから登録が始まる)
	・・・任意コード・・・	
	_debug_point(2, 10);// 1の音が登録済みの場合に、10回通過したら2のパターンの音を鳴らすように2の識別番号で登録
_debug_hex4、_debug_hex8、_debug_hex16、 _debug_hex32の第1引数nの識別番号は、それそれで0〜18の範囲で指定できます。
また、_clear_beep_code() で音の停止と初期化が可能です。

USBを介した通信

USBを介して「UME専用Hexの情報などのコマンド操作」でプログラム転送や実行開始を制御していますが、 「ウメ・エディットプログラム」内から送受信命令を使うことも可能です。 そのためのマクロは次に示します。

マクロ表現動作説明
_send_ume_id()USBへバージョン文字列(現在の文字列は"ume202304")を送信します。(改行を含みません)
_send_string(s)USBへsの文字列を送信します。(改行を含みません)
_send_decimal(d,w)USBへdのint情報を文字列に変換し、wの幅にして送信します。(改行を含みません)
+または-の符号が付きます。(wの幅に満たない場合は半角のスペースを埋めた文字列にしています。)
wが足りない場合は、拡張されて情報が抜けて出力されることはありません。
_send_padding_uint(d,c,w) USBへd(unsigned情報として扱う)を文字列に変換し、wの幅にして送信します。(改行を含みません)
+や-の符号は付きません。wの幅に満たない場合はcの文字を埋めた文字列にしています。
wが足りない場合は、足りない部分の上位桁が欠けた文字列情報になります。
例:_send_padding_uint(128,'0',5); // "00128"が送信
_send_char(c)USBへcの1バイトを送信します。(内部バッファの状態によって、すぐに送信されないことがあります。)
_send_hex_low(d)uint32_tの引数dの下位16bitを4桁16進文字列に変換してUSBへ送信します。
この文字列並びはビックエンディアンの並びで出力します。例えば(256+15)のデータは"010F"の文字列です。
(内部バッファの状態によって、すぐに送信されないことがあります。)
_send_hex_hi(d)uint32_tの引数dの上位16bitを4桁16進文字列に変換してUSBへ送信します。
(内部バッファの状態によって、すぐに送信されないことがあります。)
_send_16byte(d)uint16_tの引数のバイナリをUSBへ送信します。
2バイト、リトルエンディアン(下位バイト、次の上位バイトの順)でのUSB送信です。
(内部バッファの状態によって、すぐに送信されないことがあります。)
_set_break_buffer()上記で「内部バッファの状態によって、すぐに送信されないことがあります。」とする命令がありますが、 このバッファ内のデータを強制的に送出するように促す命令です。(ファイルストリームのflashに相当します)
_request_acc_outbuff(id)引数で割り込みに応じたidを指定をし、上記出力命令のアクセス要求をして、 取得できたら1、失敗で0を返します。
上記USBへの出力命令は、バッファリング処理をしています。 UME専用Hexの'R' 文字列コマンドによる実行呼び出し内で、上記USBへの出力命令を使う場合は問題が起こりませんが、 タイマ割り込み内から、これら出力命令を使う場合、バッファの排他制御しないと、不具合が生じます。
そこでバッファのアクセス権を要求して、取得できた場合だけ出力命令を使えばよいミューテックス (Mutex)に相当する制御を実現するものです。
引数で指定するのはcommand.hに記述される「_ID_ACCESS_XXXX」を指定します。
このXXXXの表現は割り込みの種類に応じて定義されています。
例えばTimer4の割り込み内で、上記USBへの送信命令を使う場合、
_request_acc_outbuff(_ID_ACCESS_T4_TASK)の戻り値で1が得られた場合だけ行うように使います。 そしてUSBへの送信命令使用後で、
速やかに_release_acc_outbuff(_ID_ACCESS_T4_TASK)でアクセス権を開放する必要があります。 (開放しないと、通常のUME専用Hex命令の応答や、他の割り込み内でのUSB送信ができなくなります。)
_release_acc_outbuff(id)上記の_request_acc_outbuff(id)で得たアクセス権を開放します。(戻り値なし)
_get_capacity()上記の各種USBへ出力する関数は、USBの送信バッファに記憶され、送信できるタイミングで出力す仕組みであるが、 このバッファに記憶可能な残り容量に相当する情報が戻り値です。
この値はブロック数です。(バッファは全体のブロック数が512で、1ブロック内は48byteになっています。)
_RECIVE_USB_FUNC 電源ON起動時にマクロ変数に、uint8_tを引数して何もしない戻り値0のダミー関数が記憶されています。
戻り値が0の場合、続いて「UME専用Hexコマンド」の解析・実行処理に進みます。(戻り値を1にすると、「UME専用Hexコマンド」処理をしません)
_RECIVE_USB_FUNCに受信用関数を記憶させて使います。
	//上記の各種の使い方の例
	int recive_usb(uint8_t d){
		・・・・・dの受信で呼ばれる。
	}
	・・・
	_RECIVE_USB_FUNC = recive_usb; // 受信関数作って、その関数を登録すると、受信でその関数が呼び出されます。

ADC(Analog-to-digital converter)の利用

CN8とCN9のコネクタから入力したデータは、それぞれ2段のアンプを経て、 「AN0」と「AN1」のADコンバータ入力端子に繋がれており これがADCの入力対象です。
デフォルトではADCは、「AN0」と「AN1」を交互にサンプリングしており、一つのサンプリングがTimer3の周期で決定されます。
このサンプリング周期は、「AN0」と「AN1」の2分のサンプル周期は、PR3レジスタの設定×2の値になります。
初期段階でTimer3はOFFになっているので、 これをONにするとADCも連動するようになっています。

ADCの分解能は、10bitですが16bitの符号なし整数の情報で、1024個のデータが蓄えた後に それをUSBで連続送出仕組みが作られています。 それを行うマクロが次のように用意しています。

マクロの表現概要
_set_adc_mode(c,t) ADCの対象とUSBで出力する際のモードを指定する関数で、ADCスタート前で使う。
c:ADCサンプリング対象のパラメタ
1: CN8 、2: CN9 、3: CN8とCN9 (3がデフォオルト値)
t: USBのデータ出力モードフラグ 1: TEXT MODE 、 0 : BINARY MODE (0がデフォオルト値) (このマクロを使わないで下記_set_adc_exeを使うと、2つの入力(CN8とCN9)からの信号を取り込み、 バイナリモードで出力することになる。)
_set_adc_exe(n,f) ADCのスタートと終了を制御する。(Timer3の割り込みがONでなければ、ONになります。)
n:1回分ADCサンプリングブロック数パラメタ
 nは1から63までのブロック数(1ブロックが1024ワード)nが2以下の時のPR3の最低値は100程度で、
 これは400KHz程度のサンプリングレートを意味します。
f: ループフラグで1で上記ブロックのサンプリングを繰り返す。
0で上記ブロックサンプリング後に終了する。
  (既に動作中に0の指定で呼び出すと、nは無視されて現ブロック送信で終了)
  (既に動作中に1の指定で呼び出すと、nは無視されて現ブロック送信後に、次のブロック数をnで指定可能)
上記の各種の使い方の例
	PR3=1250-1;//一つサンプリング周波数を 32KHzに指定するTimer3の割り込み周期設定パラメタ
		// AN0,AN1の2つをサンプリングするので、実質的に16KHzのサンプリング周期となります。
	_set_adc_mode(3,1);// CN8のAN0とCN9のAN1よりアナログサンプリングで出力テキストモード 
	_set_adc_exe(2 , 0);// 2block, loopしない1回だけのサンプリングで実行スタート
上記の応答のイメージを示します。
ADC_START
T1000
01FA020B01FC020B01FD020801EB020801EC020B01F1020E01F9020801FB0209
0207020B020B020A0210020D02170209020E020B01FE020701F9020A01FB0208
・・・・
021C020C021C020C02200203021C02090223020A0226020E0226020702270208
ADC_END

上記のように、ADC_STARTADC_ENDで囲んだデータをUSBで送信します。
この中の先頭行がデータの送信バイト数を意味する16進表現です。よって上記1000は4096byte数を意味していす。
(1blockが1024ワードで,指定が2blockによりX2されます。またCN8とCN9の2入力でX2され、1024×2×2=4096のbyte数です。)
この数の前にTが付く場合が16進文字列で送信されることを意味し、Tが付かない場合ばバイナリで送信されることを意味します。
上記のように、16進文字列の場合は、1WORDが4桁の16進で、1行が16WORDごとに改行("\r\n")で区切られます。
バイナリの場合はリトルエンディアンで1WORDが2byteで改行("\r\n")で区切られることはありせん。

なおADC_STARTの表現はCN8(AN0)とCN9(AN1)の2入力のサンプリングを意味します。
この時は、CN8(AN0)とCN9(AN1)のWORDが交互に並んで送信されます。
ADC_START0の表現であればCN8(AN0)の1入力のサンプリングで、
ADC_START1の表現であればCN9(AN1)の1入力のサンプリングを意味します。
ここまでの情報の受信だけで、後述されるデータの意味が分かるようになっているわけです。

_UME_ENCODE_ADC_BUFFこれは関数のポインタで、ADコンバータで得られた情報が所定の記憶域が記憶され、 次このポインタの関数を呼び出してから、USBへの出力が行われます。
ADC_STARTの出力処理の直前で呼び出されます。)
この関数へのポインタ初期値は、何もしないでただ戻る関数が記憶されているので、 このポインタを置き換えれば、その関数でADコンバータの結果を加工し、それから出力することができます。
ADコンバータで得られた情報をアクセスする場合のポインタ取得には、次の_get_ptr_adc_buffマクロを使います。
_get_ptr_adc_buff()ADコンバータで得られた情報をアクセスする場合のポインタ取得マクロです。
このポインタは、common.hで定義される「struct ADC_BUFF」の構造体を指し示すものです。
ADコンバータで得られた情報は、この構造体メンバadc_buffer0[idx_block]やadc_buffer0[idx_block]の配列です。
例えば、CN8(AN0)の入力であれば「adc_buffer0[idx_block][0〜adc_buff_data_numb-1]の内容がADCの結果の情報です。
UME_ENCODE_ADC_BUFFにセットする利用者の自作関数で、この配列内容と送出数のadc_buff_data_numbメンバ情報を変更できます。

[UMEHOSHI IT] のUART制御

デフォルトで、起動後の1秒から1秒までの間に UARTから何かを受信すると、 1回だけ"\r\n"をUARTに送信する仕組みになっています。
また、この起動後の2秒間は、UARTから受信した情報は無視されます。(この1回の応答だけします)
(これはU19にESP32-WROOM-32Dを使う場合、 デフォルトのESP32-WROOM-32Dがブートログの出力が繰り返しされる状態で、それを止める処理になっています。 ですがESP32-WROOM-32Dを使っていない場合でも、UARTを使っている場合、この起動後2秒間の処理は同じです)

マクロ表現動作説明
_init_uart1()UART1の使い方を指定します。 この関数で、 115200bps,8bit,パリティなし,1個のストップビットで使う指定にしています。 割り込みレベルを指定していますが、割り込み許可はしていません。
この初期化関数は、起動時に_HANDLES[_IDX_INIT_UART1]へ記憶され、それが実行しています。
_recv_uart1(c)USB処理のループ中で呼び出されるポーリング処理内で、 受信があれば、その受信した1byteのデータを引数cにして呼び出しています。
これは、_HANDLES[_IDX_RECV_UART1]に記憶されるマクロで、 自作関数を代入で変更することができます。
デフォルトで設定される処理は、受信したcの1byteをUSBへ送信する処理になっています。
_send_uart1(c)_HANDLES[_IDX_SEND_UART1]に記憶されるマクロです。 初期値では、UART1への送信バッファにcを入れる処理になっています。
正しくバッファにセットできれば1,バッファフルでセットできなければ0を返します。 このバッファフルの失敗時はMY_UART_ERR_SND_SET のエラー情報を内部でセットされます。
_send_string_to_uart1(s)sの文字列をUART1へ送信します。
内部的は、上記のsend_uart1の処理の繰り返しで実現しています。
_get_uart1_capacity()上記送信は、送信データを送信バッファにセットすることで動作します。
そして、バッファがフルでセットが失敗するとエラー状態になります。
そしてこのマクロは、この送信バッファに設定できる残りのバイト数を返します。
_request_acc_uartbuff(d)引数で割り込みに応じたidを指定をし、上記UART1への出力命令のアクセス要求をして、 取得できたら1、失敗で0を返します。(idはcommon.hに記載される「_ID_ACCESS_〜TASK」の識別子です)
_release_acc_uartbuff(d)上記の_request_acc_uartbuff(id)で得たアクセス権を開放します。(戻り値なし)
_my_app_tasks()システム内部ではAPP_Tasks()関数の呼び出しの繰り返しで動作しています。
そして、この中から呼び出しているのが、「テスト・ウメ・フラッシュ」専用の分岐処理をする _my_app_tasks()のマクロ処理です。
_my_app_tasks()のポインタの_HANDLES[_IDX_MY_APP_TASKS]を変更は可能ですが、 「テスト・ウメ・フラッシュ」の能力をそっくり変更する以外で変更することはないでしょう。
パワーオン時に設定されるデフォルトの関数では、USBからの受信文字列で、 「UME専用Hexコマンド」を解析して実行しています。 またこの中から下記のUARTのデフォルトポーリング送受信処理である下記の_def_polls_uart()マクロを 実行しています。
なお、パワーオン時から3秒経ったタイミングでSW2を押すと、スルーモードに移行しますが、 この変更は、_HANDLES[_IDX_MY_APP_TASKS]を変更することで実現しています。
(スルーモードとはUSBに送った情報がUARTに送られ、逆にUARTに送った情報はUSBに送られる状態)
_def_polls_uart()上記のデフォルトの_my_app_tasks()内から呼び出されるUART1のポーリング処理です。(一般に使うことがないシステム利用マクロです)
_HANDLES[_IDX_DEF_POLLS_UART]の変更で処理内容を変更できますが、初期のデフォルトでは recive_and_send_uart_with_polling関数が登録されています。
通常モードであればそこでUART1より受信を確認した場合に_recv_uart1(受信データ)を実行します。
また、UART1の送信レジスタに空きが合って送信バッファにデータ在る場合は取り出して UART1の送信レジスタに設定しています。
(UART1のポーリング処理の全体を置き換えるためものですが、一般に変更することはないでしょう。)
_cmd_polls_uart()UARTコマンドモード時のポーリング関数です。(一般に使うことがないシステム利用マクロです)
パワーオン時に、SW1とSW2を押して、SW1を離してから4秒以上後にSW2を離すと、UARTコマンドモードになりますが、 この時に使われるUARTのポーリング処理がパワーオン時に設定されます。 この処理関数のポインタが_HANDLES[_IDX_CMD_POLLS_UART]に記憶されており、 上記SWの操作時にANDLS[_IDX_DEF_POLLS_UART]をこの処理に置き換えています。
_isr_polls_uart()uartの割り込みリ利用時のポーリング処理で、_HANDLES[_IDX_ISR_POLLS_UART]に記憶されています。
デフォルトでは割り込みを使っていませんが、割り込みタンドラが定義済みです。そしてそれに対応のポーリング関数が これです。利用する場合は、_HANDLES[_IDX_DEF_POLLS_UART]へ_HANDLES[_IDX_ISR_POLLS_UART]を設定する

[UMEHOSHI IT] その他の制御

システム内部プログラムのmainは、次のように動作します。
  1. init_main()関数実行で、メモリ管理初期設定とinit_handle_area()を実行する。
    init_handle_area()の実行で
     _HANDLESの配列のパワーオン初期化と、_HANDLES[_IDX_HANDLE_USER_SET_FUNC]の関数を実行します。
     (_HANDLES[_IDX_HANDLE_USER_SET_FUNC]は、デフォルトで何もしないdummy_function関数になっている。)
  2. SYS_Initialize ( NULL )関数の実行で、MPLAB Harmony modulesの初期化(IOなどの初期化)を行う。
  3. init_interrupt()の実行で、割り込みやハンドラなどの初期化を行った後、
     EEPROM内起動関数と _HANDLES[_IDX_INIT_SUB_FUNC] の関数を実行します。
     (EEPROM内起動関数は、0x9D020000番地から実行される。)
  4. アプリケーション用メインループ(SYS_Tasks();を繰り返す処理)で、USB関連の処理を行う。
マクロ表現動作説明
_HANDLES[_IDX_HANDLE_USER_SET_FUNC]
上記で説明しているように、init_handle_area()内から呼び出されるユーザ用関数を記憶する要素です。
パワーオンの初期値は、何もしないdummy_function関数が登録されています。
登録した関数は、_handle_user_set_func()のマクロ表現で、IOなどの初期化の起動前に呼び出されます。
この要素に登録する関数では、_HANDLES[機能番号]の登録要素の変更処理を行う目的で用意しています。
変更した要素は、パワーオン時に初期値に戻りますが、単なるリセットでは戻りません。
よって、パワーオンを伴わないリセットで動作する関数の登録などに使うこともできます。
_HANDLES[_IDX_INIT_SUB_FUNC] 上記説明のinit_interrupt()内の最後で呼び出されるユーザ用関数を記憶する要素です。
パワーオンの初期値は、何もしないdummy_function関数が登録されています。
登録した関数は、_init_sub_func()のマクロ表現で、IOなどの初期化の起動後に呼び出されます。
よって、メインループに入る前に実行したい処理を登録する目的で使うことができます。
_HANDLES[_IDX_INIT_CORE_TIMER]コアタイマーの初期設定関数のポインタで、上記説明のinit_interrupt();より呼び出されます。
パワーオン時に、初期化用デフォルト関数(内部ソースにてinit_core_timer_1の関数)が記憶されます。 このデフォルト関数では、周期(_UM_CP0_SET_COMPARE)や、割り込み優先度、割り込み許可などの設定をしています。
_HANDLES[_IDX_CORE_TIMER_FUNC]コアタイマの割り込みルーチンから直接に呼び出されます。
パワーオン時に、デフォルトコアタイマの処理関数(内部ソースにてcore_timer_umeFunc_1の関数)が記憶されます。
このデフォルト関数では、_UM_CP0_SET_COMPAREマクロ変数の周期になる設定と、下記_HANDLES[_IDX_CORE_TIMER_SUB_FUNC]の関数を呼び出しています。
(_UM_CP0_SET_COMPAREの初期値は 22727uで0.00113635秒の反転周期 440Hzの周波数)
_HANDLES[_IDX_CORE_TIMER_SUB_FUNC]上記の_HANDLES[_IDX_CORE_TIMER_FUNC]のデフォルト関数から呼び出される関数ポインタを記憶
パワーオン時に、デフォルト処理関数(内部ソースにてcore_timer_sub_1の関数)が記憶されます。
このデフォルト関数では、起動時モードの切り替え処理、下記_core_wait(t)用変数のダウンカウント、ブザーの振動のON/OFF制御、SW2の監視が行われています。 代入による変更は可能ですが、単純に変更するとこれらの処理が出来なくなります。
_core_wait(t)上記_HANDLES[_IDX_CORE_TIMER_SUB_FUNC]のデフォルト処理を利用した待ち関数
引数の t は、_HANDLES[_IDX_CORE_TIMER_SUB_FUNC]の繰り返し数を指定し、その回数分の時間が経過したらリターンします。 _HANDLES[_IDX_CORE_TIMER_SUB_FUNC]の呼び出し周期は、コアタイマの割り込みと同じなので、待ち時間は_UM_CP0_SET_COMPAREの設定値に依存します。
_HANDLES[_IDX_INIT_TIMER_1]Timer1の割り込みの初期化関数のポインタを記憶し、init_interrupt()処理より呼び出されます。
パワーオン時に記憶されるデフォルト関数(内部ソースにてinit_timer_1の関数)では、0.5ミリ秒周期になていますが、Timerのスタートは 設定していません。これはサウンドのテンポに関係しており、割り込み周期は、set_switching_period(d)マクロでも変更できます。
_HANDLES[_IDX_TIMER_1_FUNC]Timer1の割り込み処理から呼び出されます。
パワーオン時に記憶されるデフォルト関数(内部ソースにてtimer1_umeFunc1_1の関数)では、サウンド再生時の音の長さ制御が行われています。

[UMEHOSHI IT] のEEPROM制御

マクロ表現動作説明
_nvm_erase_page(d)dのアドレスで示すページ(1024byte)のEEPROMの消去用マクロ。引数で指定するアドレスは、0x9D020000,
0x9D020400,0x9D020800,0x9D020c00,0x9D021000,・・・・,0x9D03E800,0x9D03EC00,の何れかを指定する。(対象ページのbyteを全て0xffに設定します。)
0x9D03E800,0x9D03EC00,を消去しないでください。
(0x9D03F800,0x9D03FC00の消去は可能です)
全てを削除するサンプルコードはこのリンク(erase.c)を参照ください。
_nvm_write_word(a,d)aのアドレス(0x9D020000〜0x9D03EC00)と(0x9D03F800〜0x9D03FC00)で示す1ワード領域に、dのワード(32bit)を書き込む
(書き込み対象のワード領域は、0xffffffffに初期化されていないと、正しく書き込めません。)
の消去は可能です)

EEPROM 領域の0x9D020000番地に関数が配置してあると、パワーオンでないリセットでその関数が実行します。
パワーオンリセットでないリセットの参考例はこちらです。

またパワーオンリセットで実行させる関数は、その関数のアドレスを0x9D03fff0番地に記憶する必要があります。そしてその関数を実行させるためには、SW2スイッチが押されてない状態で、 0x9D03fff0番地内容が0xffffffffでないという条件が必要です。
パワーオンリセットの参考例はこちらです。