音楽再生システムを作ってみた 表示機能 設計編

# 1. 今回のやりたいこと
音楽再生システムを作ります。
これを実現するためには、下記4つの機能が必要になります。
* 表示機能
* ダウンロード機能
* 音楽受信機能
* 音楽再生機能

詳細については下記リンクを参照ください。
[音楽再生システムを作ってみた (前編)](https://qiita.com/hcuymitoh/items/914df0504a8a5bbb0685)

本記事では、表示機能の設計編に関する内容を記載します。

# 2. 表示機能

表示機能の実現のためには、
* 何に表示するのか
* 画面操作をどうやってするのか
* どういう画面遷移するのか

を考える必要があります。今回の表示にはLCD、画面操作にはボタンを使用します。使用するLCD、ボタンと画面遷移の仕様について説明します。

### 2.1 使用するLCDとボタンについて
##### 2.2.1 使用するLCD
今回の表示には、LCDのＡＱＭ１６０２Ｙ－ＮＬＷ－ＢＢＷを使用します。
通信IFはI2Cとなっています。
[ＡＱＭ１６０２Ｙ－ＮＬＷ－ＢＢＷ](https://akizukidenshi.com/catalog/g/gP-12485/)

このLCDでは、16文字×2行のキャラクタを表示することができます。キャラクタのパターンは、CGROM(Character Generator ROM)と呼ばれているROMに格納されており、下記の通りとなっています。表の行は下位4ビット、列は上位4ビットのデータを表していて、例えば'A'を表示させたい場合は0b01000001(0x41)をLCDに送信すればよいことになります。
![文字列パターン.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782242/448c0253-40e5-5035-5ba3-9695de39ba11.png)



##### 2.2.2 使用するボタン
画面操作には、下記のスイッチを使用します。
[表面実装用タクトスイッチ](https://akizukidenshi.com/catalog/g/gP-15969/)

上ボタン、下ボタン、決定ボタン、戻るボタンの合計4つのボタンを使用します。

##### 2.2.3 ボードとの接続図
今回使用するボードであるnucleo l4r5ziとは下記のように接続します。
![LCD_ボード.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782242/69162d72-a17b-6d1b-56b7-ff234ba7d533.png)


### 2.2 画面遷移の仕様

画面遷移の仕様を考えてみました。
音楽再生システムの起動時の画面遷移は下記となります。
![初期画面.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782242/f6efa1d7-8dd7-c686-7ca4-82859641a238.png)

起動時には、Versionを表示しその1秒後に"サイセイ"、"ダウンロード"を表示します。上ボタン、下ボタンの入力に合わせて"▷"を選択肢の左に表示します。決定ボタンが入力されるとその時に選択されている選択肢に応じた画面遷移を行います。"サイセイ"、"ダウンロード"選択時の画面遷移を下記に示します。

* __"サイセイ"選択時__
”サイセイ”選択時は、音楽を再生します。今回の音楽再生システムでは、BlueTooth経由で受信した音楽データをリアルタイムで再生するストリーミング再生と音楽再生システム内にダウンロードされている音楽データを再生するといった2つの再生方法があります。
![サイセイ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782242/529e0a1a-bc5f-b33c-81ef-f2b0d2f4413e.png)

* __"ダウンロード"選択時__
”ダウンロード”選択時は、音楽をダウンロードします。音楽データは、BlueTooth経由で受信します。ダウンロード中に戻るボタンが入力された場合、"モドルボタンガオサレマシタ　ダウンロードヲヤメマスカ？"と表示しますが、裏ではダウンロードを続けます。戻るボタンを押して前画面に戻った時に、プログレスバーが進んだ状態で表示されることになります。
![ダウンロード.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782242/06d9e091-410d-76d7-b911-a581cdb67af7.png)


# 3. 方式設計
### 3.1 ソフトウェア構成図
表示機能のソフトウェア構成図を下記に示します。大きく4つのモジュール(HWは除く)に分けようと考えています。
![ソフトウェア構成図.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782242/a4264187-fca5-dc78-1024-0057ba1f6beb.png)


* __表示アプリ__
　「2.2 画面遷移の仕様」に記載した画面1つ毎に状態を持ちます。
　各状態にしたがって、AQM1602Y-NLW-BBW デバイスドライバに表示させる文字列を渡します。

* __AQM1602Y-NLW-BBW デバイスドライバ__
　渡された文字列を、AQM1602Y-NLW-BBWの文字列パターンに変換し、その変換したデータをI2Cドライバに渡します。
　AQM1602Y-NLW-BBWの文字列パターンは、AQM1602Y-NLW-BBW デバイスドライバで持っておきます、

* __I2Cドライバ__
　渡されたデータをI2C通信でAQM1602Y-NLW-BBWに送信します。

* __GPIOドライバ__
　ボタンの入力状態を表示アプリへ通知します。このときボタンの入力は割込みで判断することとします。

### 3.2 インターフェース　
各モジュールのインタフェースについて説明します。
##### 3.2.1 表示アプリ
|  プロトタイプ宣言 |  引数  |  戻り値  |  機能  |
| ---- | ---- | ---- | ---- |
|  uint8_t LCD_app_init(void)  |  なし  |   0  : 成功<br>-1 : 失敗  |  表示アプリの初期化を行います  |
|  uint8_t LCD_app_push_btn(uint8_t type)  |  0 : 上<br>1 : 下<br>2 : 決定<br>3 : 戻る  |  0  : 成功<br>-1 : 失敗  |  表示アプリに入力されたボタンの種類を通知します  |
|  uint8_t LCD_app_bt_connected(void)  |  なし  |  0  : 成功<br>-1 : 失敗  |  表示アプリにBlueToothが接続されたことを通知します  |
|  uint8_t LCD_app_bt_disconnected(void)  |  なし  |  0  : 成功<br>-1 : 失敗  |  表示アプリにBlueToothの接続がきれたことを通知します  |ボタンの種類を通知します  |
##### 3.2.2 AQM1602Y-NLW-BBW デバイスドライバ
|  プロトタイプ宣言 |  引数  |  戻り値  |  機能  |
| ---- | ---- | ---- | ---- |
|  uint8_t LCD_dev_init(void)  |  なし  |   0  : 成功<br>-1 : 失敗  |  AQM1602Y-NLW-BBW デバイスドライバの初期化を行います  |
|  uint8_t LCD_dev_clear_disp(void)  |  なし   |  0  : 成功<br>-1 : 失敗  |  AQM1602Y-NLW-BBW の表示をクリアします
|  uint8_t LCD_dev_write(uint8_t x, uint8_t y, uint8_t *str)  |  x : x位置(1~16)<br>y : y位置(1, 2)<br>str : 表示したい文字列 |  0  : 成功<br>-1 : 失敗  |  AQM1602Y-NLW-BBW 上の指定した位置に文字列を表示します  |

LCD_dev_write()の引数x, yには、LCDの画面を下記のように分割したときの開始位置を指定します。
![分割.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782242/6cd040a7-d54c-edc4-2b98-d01cdffa9125.png)

例えば、LCD_dev_write(9,0, "アイウエオ")、LCD_dev_write(5, 1, "カキクケコ")とした場合は下記の通りになります。
![分割_表示例.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782242/4916b1f5-216d-88be-1830-878dac0346a5.png)


画面を更新する場合は、
* LCD_dev_clear_disp()でvramをクリア
* LCD_dev_write()で表示したい文字列をLCDに送信

の流れで呼ぶこととします。

##### 3.2.3 I2Cドライバ/GPIOドライバ

I2CドライバとGPIOドライバについては、サンプルとして提供されているものを使用するので、割愛させてください。
# 4. 最後に
設計編は以上となります。
実装編は、また近々記載いたしますので少々お待ちください。

本件について、何か不明点・アドバイスがあればコメントしていただけると嬉しいです。