API collection of Ukifune. Initial publish. Documents are not ready.
ukifuneはUI基板『浮舟』のAPIモジュールです。 浮舟はNucleo F746ZGに接続して使うUI基板で、以下のような特徴を持っています。
- ピアノ鍵盤を模した13個のタクトスイッチ
- 3個のモード切り替えスイッチ
- 12個のLED
- 2ポートのI2Cを通して使える計8個のボリューム。
以下にukifuneモジュール及び浮舟について解説します。
ハードウェア
浮舟基板は、Nucleo F746ZGのCN12ヘッダーに接続して使うUI基板です。 この写真では中央下の緑の基板が浮舟です。上の白い基板はNucleo F746ZGで、その上には、変換基板桐壺を介してアクアシグナルのUMB-ADAU1361-Aが接続されています。また、浮舟の両側にはやはりアクアシグナルのTPOL-POT4-Aが接続されています。
Nucleo F746ZGのCN12は非常に多くのピンが用意されていますが、そのうち最初の50ピンのみを使っています。使用している機能はGPIO機能のほか、I2C3およびI2C4ポートです。I2C2ポートは、CN11で使えるように手付かずであけてあります。
プッシュボタンはアンチ・チャタリング回路を入れていますが、簡易型であるためあまり効きがよくありません。現時点ではキャパシタの無駄です。追試してみたい方は時定数を大きくするか、いっそアンチ・チャタリング回路をやめてもいいでしょう。
LEDもプッシュボタンも、アクティブHです。すなわち、LEDは論理状態1で点灯し、プッシュボタンを押すと論理状態が1になります。
I2Cポートは基板でプルアップした後、外部に開放しています。これらはアクアシグナルのTOL-POT4-Aに直結できるピン配置になっています。 浮舟基板にはテストポイントが3本出ています。うち1本はGNDで、残りの2本は割り込み処理時間と信号処理時間を測定するためのステータスピンです。
ソフトウェア
ukifuneモジュールは浮舟基板制御用のAPI群です。これらは名前空間ukifuneでラップされており、ukifune.hを読むことで利用できます。 APIの一覧については、このページのAPI Documentationタブを参照してください。APIドキュメントには、LEDおよびプッシュ・ボタン・スイッチをプログラムから参照するための識別子も列挙してあります。
ukifuneモジュールのAPIを使用するためには、事前にukifune::init() APIを一度だけ呼ぶ必要があります。このAPIは内部変数を初期化するほか、雲仙オーディオフレームワークへのポインタを受け取り、フレームワークに対してテストピンを駆動するためのコールバック群を登録します。
ボリュームを使う場合には、周期的に ukifune::tick() を呼んでください。このAPIは呼ばれるたびにI2C経由でADCにアクセスしてアナログ値を読み取り、ukifuneモジュールの内部変数を更新します。呼び出し周期はおおむね50mS以内であれば十分でしょう。周期の精度については適当でかまいません。
プッシュボタンの状態を知りたい場合には、ukifune::get_button_state() を呼び出します。このAPIは3つのビットマスクを返します。
pushing 引数は、前回のAPI呼び出し時からどのボタンが押し込まれたかを返します。言い換えると、前回押されていなかったにもかかわらず、今回のAPI呼び出しで押されていることが検出されたボタンがこの変数から返されます。pushing引数はビットマップであり、ビット位置は enum ukifune::SWITCHの要素の値に対応します。対応するビットが1であるようなスイッチが、押し込まれたスイッチです。
releasing 引数は、前回のAPI呼び出し時からどのボタンが戻されたかを返します。言い換えると、前回押されていたにもかかわらず、今回のAPI呼び出しで押されていないことが検出されたプッシュボタンがこの変数から返されます。releasing引数はビットマップであり、ビット位置は enum ukifune::SWITCHの要素の値に対応します。対応するビットが1であるようなスイッチが、戻されたスイッチです。
pushed 引数は、どのボタンが押されているかを返します。pushed引数はビットマップであり、ビット位置は enum ukifune::SWITCHの要素の値に対応します。対応するビットが1であるようなスイッチが、押されているスイッチです。
ukifune::get_volume()は、ボリュームの状態を返します。引数は0から7の整数で、ボリュームに対応します。返り値の範囲は0から1.0です。
基板設計情報およびパーツリスト
ukifuneの 基板設計情報をアップロードしておきます( 2017/01/28, ver 2 )。
この基板はKiCad 4.0.2 で設計し、出力したgerberデータをスイッチサイエンスの基板製造サービスで製造し、動作を確認しています(写真)。万に一つのことがありますので、基板を外注に出す方は、くれぐれも事前の注意を払ってください。また、この基板は実験用に作成したものであり、民生、産業、医療などの用途に耐えるような設計ではありません。どのような理由であれ、この基板によって発生した問題については責任を取りません。
部品表は以下の通りです。C1の脚の幅にご注意ください。LEDやプッシュボタン・スイッチの色は任意です。なお、U1だけは表面実装部品です。ご注意ください。 以下の部品の他に、Nucleo側のピンヘッダおよび、基板接続用のフラットケーブル(圧接コネクタ付き)が必要です。
Reference | Value | Footprint | 注釈 |
---|---|---|---|
C1 | 0.1u | Capacitors_ThroughHole:C_Disc_D3_P2.5 | 0.1uF ピン幅2.54mm |
C2 | 10u | Capacitors_ThroughHole:C_Radial_D5_L6_P2.5 | 10uF ピン幅2.54mm |
C3 | 0.1u | Capacitors_ThroughHole:C_Disc_D6_P5 | 0.1uF ピン幅5.08mm |
C4 | 0.1u | Capacitors_ThroughHole:C_Disc_D6_P5 | 0.1uF ピン幅5.08mm |
C5 | 0.1u | Capacitors_ThroughHole:C_Disc_D6_P5 | 0.1uF ピン幅5.08mm |
C6 | 0.1u | Capacitors_ThroughHole:C_Disc_D6_P5 | 0.1uF ピン幅5.08mm |
C7 | 0.1u | Capacitors_ThroughHole:C_Disc_D6_P5 | 0.1uF ピン幅5.08mm |
C8 | 0.1u | Capacitors_ThroughHole:C_Disc_D6_P5 | 0.1uF ピン幅5.08mm |
C9 | 0.1u | Capacitors_ThroughHole:C_Disc_D6_P5 | 0.1uF ピン幅5.08mm |
C10 | 0.1u | Capacitors_ThroughHole:C_Disc_D6_P5 | 0.1uF ピン幅5.08mm |
C11 | 0.1u | Capacitors_ThroughHole:C_Disc_D6_P5 | 0.1uF ピン幅5.08mm |
C12 | 0.1u | Capacitors_ThroughHole:C_Disc_D6_P5 | 0.1uF ピン幅5.08mm |
C13 | 0.1u | Capacitors_ThroughHole:C_Disc_D6_P5 | 0.1uF ピン幅5.08mm |
C14 | 0.1u | Capacitors_ThroughHole:C_Disc_D6_P5 | 0.1uF ピン幅5.08mm |
C15 | 0.1u | Capacitors_ThroughHole:C_Disc_D6_P5 | 0.1uF ピン幅5.08mm |
C16 | 0.1u | Capacitors_ThroughHole:C_Disc_D6_P5 | 0.1uF ピン幅5.08mm |
C17 | 0.1u | Capacitors_ThroughHole:C_Disc_D6_P5 | 0.1uF ピン幅5.08mm |
C18 | 0.1u | Capacitors_ThroughHole:C_Disc_D6_P5 | 0.1uF ピン幅5.08mm |
D1_1 | LED | LEDs:LED-3MM | LED ピン幅2.54mm |
D1_2 | LED | LEDs:LED-3MM | LED ピン幅2.54mm |
D1_3 | LED | LEDs:LED-3MM | LED ピン幅2.54mm |
D1_4 | LED | LEDs:LED-3MM | LED ピン幅2.54mm |
D2_1 | LED | LEDs:LED-3MM | LED ピン幅2.54mm |
D2_2 | LED | LEDs:LED-3MM | LED ピン幅2.54mm |
D2_3 | LED | LEDs:LED-3MM | LED ピン幅2.54mm |
D2_4 | LED | LEDs:LED-3MM | LED ピン幅2.54mm |
D3_1 | LED | LEDs:LED-3MM | LED ピン幅2.54mm |
D3_2 | LED | LEDs:LED-3MM | LED ピン幅2.54mm |
D3_3 | LED | LEDs:LED-3MM | LED ピン幅2.54mm |
D3_4 | LED | LEDs:LED-3MM | LED ピン幅2.54mm |
P1 | CONN_02X25 | Pin_Headers:Pin_Header_Straight_2x25 | ピンヘッダ 2x25 2.54mm |
P2 | CONN_02X05 | Pin_Headers:Pin_Header_Straight_2x05 | ピンヘッダ 2x5 2.54mm |
P3 | CONN_02X05 | Pin_Headers:Pin_Header_Straight_2x05 | ピンヘッダ 2x5 2.54mm |
R1 | 660 | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 660Ω 炭素皮膜 |
R2 | 660 | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 660Ω 炭素皮膜 |
R3 | 660 | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 660Ω 炭素皮膜 |
R4 | 660 | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 660Ω 炭素皮膜 |
R5 | 660 | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 660Ω 炭素皮膜 |
R6 | 660 | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 660Ω 炭素皮膜 |
R7 | 660 | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 660Ω 炭素皮膜 |
R8 | 660 | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 660Ω 炭素皮膜 |
R9 | 660 | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 660Ω 炭素皮膜 |
R10 | 660 | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 660Ω 炭素皮膜 |
R11 | 660 | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 660Ω 炭素皮膜 |
R12 | 660 | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 660Ω 炭素皮膜 |
R13 | 330k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 330kΩ 炭素皮膜 |
R14 | 330k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 330kΩ 炭素皮膜 |
R15 | 330k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 330kΩ 炭素皮膜 |
R16 | 330k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 330kΩ 炭素皮膜 |
R17 | 330k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 330kΩ 炭素皮膜 |
R18 | 330k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 330kΩ 炭素皮膜 |
R19 | 330k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 330kΩ 炭素皮膜 |
R20 | 330k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 330kΩ 炭素皮膜 |
R21 | 330k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 330kΩ 炭素皮膜 |
R22 | 330k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 330kΩ 炭素皮膜 |
R23 | 330k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 330kΩ 炭素皮膜 |
R24 | 330k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 330kΩ 炭素皮膜 |
R25 | 330k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 330kΩ 炭素皮膜 |
R26 | 330k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 330kΩ 炭素皮膜 |
R27 | 330k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 330kΩ 炭素皮膜 |
R28 | 330k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 330kΩ 炭素皮膜 |
R29 | 2.2k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 2.2kΩ 炭素皮膜 |
R30 | 2.2k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 2.2kΩ 炭素皮膜 |
R31 | 2.2k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 2.2kΩ 炭素皮膜 |
R32 | 2.2k | Resistors_ThroughHole:Resistor_Horizontal_RM7mm | 2.2kΩ 炭素皮膜 |
SWM1 | SPST | Buttons_Switches_ThroughHole:SW_PUSH_6mm | タクトスイッチ |
SWM2 | SPST | Buttons_Switches_ThroughHole:SW_PUSH_6mm | タクトスイッチ |
SWM3 | SPST | Buttons_Switches_ThroughHole:SW_PUSH_6mm | タクトスイッチ |
SWK1 | SPST | Buttons_Switches_ThroughHole:SW_PUSH_6mm | タクトスイッチ |
SWK2 | SPST | Buttons_Switches_ThroughHole:SW_PUSH_6mm | タクトスイッチ |
SWK3 | SPST | Buttons_Switches_ThroughHole:SW_PUSH_6mm | タクトスイッチ |
SWK4 | SPST | Buttons_Switches_ThroughHole:SW_PUSH_6mm | タクトスイッチ |
SWK5 | SPST | Buttons_Switches_ThroughHole:SW_PUSH_6mm | タクトスイッチ |
SWK6 | SPST | Buttons_Switches_ThroughHole:SW_PUSH_6mm | タクトスイッチ |
SWK7 | SPST | Buttons_Switches_ThroughHole:SW_PUSH_6mm | タクトスイッチ |
SWK8 | SPST | Buttons_Switches_ThroughHole:SW_PUSH_6mm | タクトスイッチ |
SWK9 | SPST | Buttons_Switches_ThroughHole:SW_PUSH_6mm | タクトスイッチ |
SWK10 | SPST | Buttons_Switches_ThroughHole:SW_PUSH_6mm | タクトスイッチ |
SWK11 | SPST | Buttons_Switches_ThroughHole:SW_PUSH_6mm | タクトスイッチ |
SWK12 | SPST | Buttons_Switches_ThroughHole:SW_PUSH_6mm | タクトスイッチ |
SWK13 | SPST | Buttons_Switches_ThroughHole:SW_PUSH_6mm | タクトスイッチ |
TP1 | TEST_1P | Pin_Headers:Pin_Header_Straight_1x01 | |
TP2 | TEST_1P | Pin_Headers:Pin_Header_Straight_1x01 | |
TP3 | TEST_1P | Pin_Headers:Pin_Header_Straight_1x01 | |
U1 | TA48M033F | TO_SOT_Packages_SMD:TO-252-2Lead | SMD 3.3V レギュレータ |
Nucleo F746ZGの改造
Nucleo F746ZGは非常に多機能なSoCマイコンを使っています。多くの機能がピンに多重化されているものの、一部は基板外の複数の信号がピンを奪い合う形になっています。これを解決するために、Nucleo F746ZGには多くのショート・ブリッジがあります。
浮舟基板を使うためにはNucleo F746ZGの以下のショート・ブリッジを取り去ってください。
- SB125
- SB132
- SB133
- SB178
- SB181
また、以下のジャンパー・ピンはオープンにしてください。
- JP6
- JP7
以上の改造によって、Nucelo F746ZGのEthernetポートおよび、USB OTGポートが使用できなくなります(ホストと接続しているmbed用USBポートには影響はありません)。
既知の問題
- アンチ・チャタリング回路は見直した方がいいです。現状でチャタリングが残っています。
- C1は他のキャパシタと異なり、2.54mmピッチです。
参考リンク
- 『雲仙』 オーディオ・フレームワーク : フレームワークの全体像の解説。CODEC基板アダプタの設計情報
- skeleton_unzen_nucleo_f746 Nucleo F746ZGおよびUI基板を使う場合のスケルトンプログラム。F746を使う方はここから読み始めると良いでしょう。
ukifune.cpp
- Committer:
- shorie
- Date:
- 2017-01-28
- Revision:
- 7:e2a690a654ff
- Parent:
- 1:6253da3ab855
File content as of revision 7:e2a690a654ff:
#include "mbed.h" #include "ukifune.h" #include "unzen.h" #include "amakusa.h" #define AD7999 (0x29<<1) #define ADCBUFSIZE 8 #define ADCNUM 8 namespace ukifune { // DigitalOut *leds[12]; DigitalIn *switches[16]; float adc[ADCNUM]; amakusa::Hysteresis * hysteresis[ADCNUM]; // Test points DigitalOut TP1( PE_12 ); // TP1 for _interrupt _flag. DigitalOut TP2( PF_14 ); // TP2 for _process _flag. // LED DigitalOut LED1_1(PE_7); DigitalOut LED1_2(PF_10); DigitalOut LED1_3(PF_4); DigitalOut LED1_4(PC_4); DigitalOut LED2_1(PB_13); DigitalOut LED2_2(PB_5); DigitalOut LED2_3(PB_14); DigitalOut LED2_4(PB_15); DigitalOut LED3_1(PB_6); DigitalOut LED3_2(PA_11); DigitalOut LED3_3(PA_5); DigitalOut LED3_4(PC_6); // Mode Button DigitalIn SWM1(PD_14); DigitalIn SWM2(PB_4); DigitalIn SWM3(PA_12); // Key Button DigitalIn SWK1(PE_10); DigitalIn SWK2(PD_15); DigitalIn SWK3(PD_11); DigitalIn SWK4(PE_8); DigitalIn SWK5(PF_5); DigitalIn SWK6(PA_10); DigitalIn SWK7(PB_1); DigitalIn SWK8(PB_12); DigitalIn SWK9(PA_7); DigitalIn SWK10(PA_6); DigitalIn SWK11(PC_7); DigitalIn SWK12(PC_5); DigitalIn SWK13(PC_8); // I2S ports for potentiometer I2C i2c3(PC_9, PA_8); // SDA, SCL of I2C3 I2C i2c4(PD_13, PD_12); // SDA, SCL of I2C4 void assert_process_flag( void ) { TP2 = 1; } void deassert_process_flag( void ) { TP2 = 0; } void assert_interrupt_flag( void ) { TP1 = 1; } void deassert_interrupt_flag( void ) { TP1 = 0; } void init( unzen::Framework *audio) { // Setup interrupt/process activity flag. audio->set_pre_interrupt_callback( assert_interrupt_flag ); audio->set_post_interrupt_callback( deassert_interrupt_flag ); audio->set_pre_process_callback( assert_process_flag ); audio->set_post_process_callback( deassert_process_flag ); // Setup LEDs leds[ led1_1 ] = &LED1_1; leds[ led1_2 ] = &LED1_2; leds[ led1_3 ] = &LED1_3; leds[ led1_4 ] = &LED1_4; leds[ led2_1 ] = &LED2_1; leds[ led2_2 ] = &LED2_2; leds[ led2_3 ] = &LED2_3; leds[ led2_4 ] = &LED2_4; leds[ led3_1 ] = &LED3_1; leds[ led3_2 ] = &LED3_2; leds[ led3_3 ] = &LED3_3; leds[ led3_4 ] = &LED3_4; // Setup Switches switches[ swm1 ] = & SWM1; switches[ swm2 ] = & SWM2; switches[ swm3 ] = & SWM3; switches[ swk1 ] = & SWK1; switches[ swk2 ] = & SWK2; switches[ swk3 ] = & SWK3; switches[ swk4 ] = & SWK4; switches[ swk5 ] = & SWK5; switches[ swk6 ] = & SWK6; switches[ swk7 ] = & SWK7; switches[ swk8 ] = & SWK8; switches[ swk9 ] = & SWK9; switches[ swk10 ] = & SWK10; switches[ swk11 ] = & SWK11; switches[ swk12 ] = & SWK12; switches[ swk13 ] = & SWK13; for ( int i= 0; i<ADCNUM; i++ ) hysteresis[ i ] = new amakusa::Hysteresis((int32_t)0,(int32_t) 255); } void get_button_state( uint32_t & pusshing, uint32_t & releasing, uint32_t & holding ) { static int last_button = 0; int current_button = 0; int index; // get current button mask pattern index = 0; for ( int sw = 0; sw < 16; sw ++ ) { if ( *(switches[sw]) ) current_button |= 1<<index; index ++; } // return pushed button holding = current_button; // buttons which are pushed from last state. pusshing = ( last_button ^ current_button ) & current_button; // buttons which are released from last state releasing = ( last_button ^ current_button ) & last_button; last_button = current_button; } void turn_led_on( enum LED led ) { *( leds[ led ] ) = 1; } void turn_led_off( enum LED led ) { *( leds[ led ] ) = 0; } void toggle_led( enum LED led ) { *( leds[ led ] ) = ! get_led_state( led ); } int get_led_state( enum LED led ) { return *( leds[ led ] ); } float get_volume( int number ) { if ( number < 0) return 0.0; if ( number >= ADCNUM ) return 0.0; return adc[ number ]; } void parse_adc( char * buf, int &ch, int &data ) { ch = ( buf[0] & 0x30 ) >> 4; data = ( buf[0] & 0x0F ) << 4 | ( buf[1] & 0xF0 ) >> 4; } void tick(void) { char adcbuf[ADCBUFSIZE]; int ch, data; i2c3.read( AD7999, adcbuf, 8); parse_adc(& adcbuf[0], ch, data); adc[ch] = hysteresis[ch]->run( data ) / 255.0; parse_adc(& adcbuf[2], ch, data); adc[ch] = hysteresis[ch]->run( data ) / 255.0; parse_adc(& adcbuf[4], ch, data); adc[ch] = hysteresis[ch]->run( data ) / 255.0; parse_adc(& adcbuf[6], ch, data); adc[ch] = hysteresis[ch]->run( data ) / 255.0; i2c4.read( AD7999, adcbuf, 8); parse_adc(& adcbuf[0], ch, data); adc[ch+4] = hysteresis[ch+4]->run( data ) / 255.0; parse_adc(& adcbuf[2], ch, data); adc[ch+4] = hysteresis[ch+4]->run( data ) / 255.0; parse_adc(& adcbuf[4], ch, data); adc[ch+4] = hysteresis[ch+4]->run( data ) / 255.0; parse_adc(& adcbuf[6], ch, data); adc[ch+4] = hysteresis[ch+4]->run( data ) / 255.0; } };