2023年8月17日木曜日

BlackFinを使ってみるなり(18) お休み前、PCからUART経由で制御

明日からリフォームのひらりんです.

リフォームで多忙になる前にBlackFin BF706で動作確認を終わらせておきたかったことはほぼ出来ました.

今日はUART Rxを動かして、PCからUSB COMでDSPを制御しました.

今まで、UARTの設定がよくわからず例外が発生していたのですが、以下の設定で動きました.UART0のTxRx両方使いです.全二重と呼びますか?
例外の原因は、赤字のメモリサイズでした.TxまたはRxの場合のメモリサイズは小さくていいが、両方向は大きなメモリサイズが必要です.BIDIRとは両方向のことです.
adi_uart_Open(0, ADI_UART_DIR_BIDIRECTION, driverMemory_uart, ADI_UART_BIDIR_DMA_MEMORY_SIZE, &hDevice);
adi_uart_SetMode(hDevice, ADI_UART_MODE_UART);
adi_uart_SetBaudRate(hDevice, 115200);
adi_uart_SetParity(hDevice, ADI_UART_NO_PARITY);
adi_uart_SetNumStopBits(hDevice, ADI_UART_ONE_STOPBIT);
adi_uart_SetWordLen(hDevice, ADI_UART_WORDLEN_8BITS);
adi_uart_EnableDMAMode(hDevice, true);
adi_uart_RegisterCallback(hDevice, UARTCallback, (void*)0);

adi_uart_SubmitTxBuffer(hDevice, txbuf_uart[0], 1);
adi_uart_EnableTx(hDevice, true);

adi_uart_SubmitRxBuffer(hDevice, rxbuf_uart, 1);
adi_uart_EnableRx(hDevice, true);

Tx側は以前の投稿を読んでもらうとして、今回はRx側です.

Rxはどうも使い心地が悪いかなぁ.現状のRxのやりかたをポエム風に表現するとこうです.
 ・DMAである
 ・1BYTE Rxの要求を出す
 ・1BYTE Rxが完遂されたら割り込みcallbackが生じる
 ・callbackの内部で、その1文字を自前のバッファに積む
 ・CRを受信したらコマンド解析などを行う
この「1文字毎にcallback処理する」のってなんかのろくさくて好かないんだけど.
もちろん、50文字Rxという要求を出すのも可能なのですが、それだとコマンド列の末尾で50文字に満たず無反応になってしまうので受諾できません.なので1文字毎にしてます.
または、pollingで「Rxしたぁ?」「何文字?」みたいな関数も用意されてるみたいなのですが、なんのためのDMAなのかなと思ってしまいますが、1文字毎にDMAで受信してるパープリンの言う事じゃねぇや、と思わんでもなく.なんか居心地悪いです.

callback関数の1文字処理のところ.
①ADI_UART_EVENT_RX_BUFFER_PROCESSEDというevent flagが受信完了の意味.
②すぐに受信文字をsaveしといてから、
③次の1文字をRxしろと要求する
④UARTへecho back
⑤CR受信で行末検出
⑥1行受信のflagを立てる
void UARTCallback(){
 switch (event) {
  case ADI_UART_EVENT_RX_BUFFER_PROCESSED: ①
   char x = rxbuf_uart[0]; ②
   adi_uart_SubmitRxBuffer(hDevice_uart, rxbuf_uart, 1); ③
   h_uart_tx_char(x); ④
   switch (x) {
    case 0x0d: ⑤
     comN = N;
     if(N==0 && i==0) break; // no character
     N=0; i=0;
     bComplete_uart_CR = true; // end of a line ⑥
   break;

⑥のフラグをmain()のloopでチェックしていまして、そこでコマンド解析し、DACに発生させる周波数、電圧、波形などを変更します.結果として、BF706をPCから制御していることになります.
制御コマンドはこんな感じです.
 f r 600   Rchを600Hzにする
 a l 67    Lchの電圧をフルスケールの67%にする

32bitのsin(x)を67%に小さくする演算って固定小数点だとどうやるんだろう???
浮動小数点で表現するとこんなに簡単なわけですが、、、
 out = sin(x) * 67 / 100;
固定小数点だと現状はこんなにしています.かったるくない?
 long long t64 = mult64_32x32( 0x7fffffff, 67 );
 int t32 = t64 / 100;
 o = sin_fr32( x );
 o = mult_fr1x32x32( o, t32 );
 out = polarity==true ? o : (-1)*o; ←前回書いた極性制御
赤字の乗算関数はライブラリが提供するものです.

ーーーー
CrossCoreのproject詰め合わせはこちらです.

BF706のサンプルとしてどんな事を見れるかというと、、、
・BF706評価ボードがtarget
・Timer0でLEDチカチカ(GPIOも)
・Timer1でUARTの周期的送信(10Hzだったかな)
・UART0 Tx 内部状態をPCへ送信
・UART0 Rx PCからBF706を制御する
・SPORTのI2SでDACへ音声データ送信
・sin_fr32(x)で固定小数点でsin波発生→DAC出力
・speed tuneはなにもやってません、だらだらcodeです

免責:被害に遭っても知りません.

明日からDSPのupdateは遅くなりますのでまたね~

17へ      19へ

かしこ

0 件のコメント:

コメントを投稿