AVTOKYO 2019 Badge をサンプルプログラムで遊ぼう！

低レベル勉強会がAVTOKYO 2019用に作ったバッジ。

![IMG_20191102_104525.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/ee955171-f66f-4de7-2c6c-c9b6d8f72117.jpeg)

# ハードウェアの説明

「STM32 マイコンボードに 48 キーボードを実装」
https://qiita.com/nanbuwks/items/7c76bfd9360b68a3793c

# AVTokyo2017 Badge との互換性

ハードウェアは互換性があり、同じように使うことができます。
しかしながらソフトウェア開発の環境が異なります。

頒布しているキットには、Bootloader をインストールしていません。プログラムは ST-Link で書き込むとして環境設定を行う必要があります。

# 最初の設定

- Arduino開発環境インストール
- STM32_Arduinoインストール
- ライブラリインストール

必要なライブラリは以下のみです。

- Adafruit GFX Library

以下を見てインストールしてください
「inside of AVTOKYO 10th HACK BADGE」
https://qiita.com/lowlevel/items/0fd3402e0dd4584de65f

# Lチカ
以下、サンプルプログラムを使って動かしていきます。
まずはLEDを点滅するプログラムです。


```

void setup() {
  pinMode(PC13,OUTPUT);
}
void loop() {
  digitalWrite(PC13,HIGH);
  delay(100);
  digitalWrite(PC13,LOW);
  delay(900);
}
```
![IMG_20191124_083258.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/f536968a-8abe-afea-653a-0387a57c81d9.jpeg)

# OLED で画面表示

OLEDサンプルプログラムを呼び出す

![image](https://qiita-image-store.s3.amazonaws.com/0/139524/e448d1fb-6d40-43a7-cd27-b21feef4ffc3.png)
「Generic STM32F103C series用のスケッチ例」から、ssd1306_128x64_spiを使ってみます。


```
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// If using software SPI (the default case):
#define OLED_MOSI   9
#define OLED_CLK   10
#define OLED_DC    11
#define OLED_CS    12
#define OLED_RESET 13
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

```
を以下のように変える

```

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306_STM32.h>

// If using software SPI (the default case):
#define OLED_MOSI   PA7
#define OLED_CLK   PA5
#define OLED_DC    PA6
#define OLED_CS    PA4
#define OLED_RESET PA3
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
```
![IMG_20191124_083142.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/74a1769a-6b3c-37c0-5b70-9061dd9ad838.jpeg)


# キーボードチェック

キーボード部分のスイッチが動作するかどうかのテストプログラムです。

```

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_SSD1306_STM32.h>

#define OLED_MOSI  PA7
#define OLED_CLK   PA5
#define OLED_DC    PA6
#define OLED_CS    PA4
#define OLED_RESET PA3 
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

#define BUTTONA PA0
#define BUTTONB PC14
#define BUTTONUP PB5
#define BUTTONDOWN PB6

#define KEYX0 PB1
#define KEYX1 PA2
#define KEYX2 PA1
#define KEYX3 PC15 // PC15 source is 0mA (Use Open Drain mode)
#define KEYX4 PB9
#define KEYX5 PB4

#define KEYY0 PB3
#define KEYY1 PA10
#define KEYY2 PA9
#define KEYY3 PA8
#define KEYY4 PB15
#define KEYY5 PB14
#define KEYY6 PB13
#define KEYY7 PB12

int i,counter=0;
int keyY[8]={KEYY0,KEYY1,KEYY2,KEYY3,KEYY4,KEYY5,KEYY6,KEYY7};
int keyX[6]={KEYX0,KEYX1,KEYX2,KEYX3,KEYX4,KEYX5};

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

void setup()   {                
  display.begin(SSD1306_SWITCHCAPVCC);
  display.display();
  delay(1000);

  disableDebugPorts();  // for use  PA15/PB3/PB4
  pinMode(BUTTONUP,INPUT_PULLDOWN);
  pinMode(BUTTONDOWN,INPUT_PULLDOWN);
  pinMode(BUTTONB,INPUT_PULLDOWN);
  pinMode(BUTTONA,INPUT_PULLDOWN);

  pinMode(KEYX0,OUTPUT_OPEN_DRAIN);
  pinMode(KEYX1,OUTPUT_OPEN_DRAIN);
  pinMode(KEYX2,OUTPUT_OPEN_DRAIN);
  pinMode(KEYX3,OUTPUT_OPEN_DRAIN);
  pinMode(KEYX4,OUTPUT_OPEN_DRAIN);
  pinMode(KEYX5,OUTPUT_OPEN_DRAIN);

  pinMode(KEYY0,INPUT_PULLUP);
  pinMode(KEYY1,INPUT_PULLUP);
  pinMode(KEYY2,INPUT_PULLUP);
  pinMode(KEYY3,INPUT_PULLUP);
  pinMode(KEYY4,INPUT_PULLUP);
  pinMode(KEYY5,INPUT_PULLUP);
  pinMode(KEYY6,INPUT_PULLUP);
  pinMode(KEYY7,INPUT_PULLUP);

  Serial.println("start ...");
  delay(100); 
 
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0,0);  
  display.setTextColor(WHITE,BLACK);

}

void loop() {
    int keyx=0,keyy=0;
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0,0);  
    display.println("   -   keycheck   -");
    digitalWrite(KEYX0,1);
    digitalWrite(KEYX1,1);
    digitalWrite(KEYX2,1);
    digitalWrite(KEYX3,1);
    digitalWrite(KEYX4,1);
    digitalWrite(KEYX5,1);
    for ( int x=0; x<6;x++){
      digitalWrite(keyX[x],0);
      int key=0;
      for ( int y=0; y<8;y++){
        if ( 0==digitalRead(keyY[y])){ display.print(1);} else {display.print(0);}
        display.print(" ");
      }
      display.println();
      digitalWrite(keyX[x],1);
      delay(10);
    }
    display.display();
    delay(200);
}
```

![IMG_20191124_091225.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/b80a960f-a3d6-efb8-3819-46aa30279e11.jpeg)

# 文字を出す

先のプログラムのloop近辺を以下のように変更します。

```
char* keymap[6][8]= {
  {"1","Symbol","TAB","Ctrl","Enter","ESC","BS","0"},
  {"2","w","q","x","s","d","e","3"},
  {"5","t","g","c","v","f","r","4"},
  {"6","y","h","n","b","j","u","7"},
  {"9","o","p","m","l","k","i","8"},
  {"space","Caps","a","z","UP","DOWN","LEFT","RIGHT"}
};

void loop() {
    int keyx=0,keyy=0;
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0,0);  
    display.println("   -   keycheck   -");
    digitalWrite(KEYX0,1);
    digitalWrite(KEYX1,1);
    digitalWrite(KEYX2,1);
    digitalWrite(KEYX3,1);
    digitalWrite(KEYX4,1);
    digitalWrite(KEYX5,1);
    for ( int x=0; x<6;x++){
      digitalWrite(keyX[x],0);
      int key=0;
      for ( int y=0; y<8;y++){
        if ( 0==digitalRead(keyY[y])){ display.print(keymap[x][y]);}
        display.print(" ");
      }
      display.println();
      digitalWrite(keyX[x],1);
      delay(10);
    }
    display.display();
    delay(200);
}

```
![IMG_20191124_092832.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/6dce41ac-1359-f3af-307f-939d62586c6a.jpeg)

# パソコンのキーボードにする

以下のプログラムを実行し、USBケーブルをPCに接続するとキーボードのように動かすことができます。

```

#include <USBComposite.h>
USBHID HID;
HIDKeyboard Keyboard(HID);
 
void setup() {
  HID.begin(HID_KEYBOARD_MOUSE);
  delay(2000);
}

void loop() {
  Keyboard.println("Hello!");
  delay(5000);
}
```
![IMG_20191124_094851.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/dfe267b2-5b22-fda1-1bdb-ba99f6f89b3c.jpeg)

# さらなるチャレンジ！

- キーボードで入力した文字をパソコンに送ってみよう
- Capsを押すと英語の大文字にするには？
- 文章を入力して画面に出すようにするには？


# トラブルシューティング

以下のようになった場合

```

2019-11-24T08:44:22 INFO src/stlink-common.c: Loading device parameters....
2019-11-24T08:44:22 WARN src/stlink-common.c: unknown chip id! 0xe0042000

```

ジャンパーを切り替えます。

![IMG_20191124_083325.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/76f677a1-ffb3-fd1d-8011-214a313342fe.jpeg)
↑これは通常の場合

![IMG_20191124_083344.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/0544bfe9-493f-15e9-b4c0-d88cfa675fe9.jpeg)
↑このようにジャンパーを付け替えてリセットし、書き込みをします。