0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

任天堂GBAボタン入力判定

0
Posted at

目的

GBAのボタン入力を識別する仕組みを整える。

ビルド

リンカスクリプト及びROMのヘッダファイルは以下の記事のものを使用する。
ビルドの手順は筆者の以下の記事を参考
GBA自作コードを実機で動作させる手順

arm-none-eabi-as header.s -o header.o
arm-none-eabi-gcc -c main.c  -o main.o -nostdlib -ffreestanding
arm-none-eabi-gcc -c font.c  -o font.o -nostdlib -ffreestanding
arm-none-eabi-ld header.o main.o font.o -T link.ld -o out.elf
arm-none-eabi-objcopy -O binary out.elf out.gba

結果

ボタンを押す毎に対応する番号を表示していく。
写真は全てのボタンを押した後の様子。
0eab4a43dd0d7

ボタン判定の原理

0x04000130から16ビットの値を読み取る。
0から9ビット目がそれぞれのボタンに対応している。
押していない時は1、押している時は0となる。

具体例を下に挙げる。

Aを押してない key=1111 1111 1111 1111

key & KEY_A

1111 1111 1111 1111
0000 0000 0000 0001
--------------------
0000 0000 0000 0001

!(key & KEY_A) = !(1) → false

Aを押している key=1111 1111 1111 1110

key & KEY_A

1111 1111 1111 1110
0000 0000 0000 0001
--------------------
0000 0000 0000 0000

結果 = 0(押している)

検証コード

main.c
#include "font.h"

typedef unsigned char  uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int   uint32_t;

#define REG_DISPCNT (*(volatile unsigned int*)0x04000000)
#define MODE3 3
#define BG2_ENABLE (1 << 10)

#define VRAM ((volatile uint16_t*)0x06000000)
#define KEYINPUT (*(volatile unsigned short*)0x04000130) // 各ボタン押下状況が返る

// 各ボタン押下有無判別用マスク
#define KEY_A      (1 << 0) // 0000 0000 0000 0001
#define KEY_B      (1 << 1) // 0000 0000 0000 0010
#define KEY_SELECT (1 << 2) // 0000 0000 0000 0100
#define KEY_START  (1 << 3) // 0000 0000 0000 1000
#define KEY_RIGHT  (1 << 4) // 0000 0000 0001 0000
#define KEY_LEFT   (1 << 5) // 0000 0000 0010 0000
#define KEY_UP     (1 << 6) // 0000 0000 0100 0000
#define KEY_DOWN   (1 << 7) // 0000 0000 1000 0000
#define KEY_R      (1 << 8) // 0000 0001 0000 0000
#define KEY_L      (1 << 9) // 0000 0010 0000 0000

static inline void putpixel(int x, int y, uint16_t c) {
    VRAM[y * 240 + x] = c;
}

void draw_hex(int x, int y, int v, uint16_t color) {
    for (int row = 0; row < 8; row++) {
        uint8_t bits = font[v][row];

        for (int col = 0; col < 8; col++) {
            if (bits & (1 << (7 - col))) {
                putpixel(x + col, y + row, color);
            }
        }
    }
}

int main(void) {
    REG_DISPCNT = MODE3 | BG2_ENABLE;

    for (int i = 0; i < 240 * 160; i++)VRAM[i] = 0;

    while (1) {
        unsigned short key = KEYINPUT;

        if (!(key & KEY_A)) { // Aボタン押下 
            draw_hex(10, 10, 0, 0xFFFF);
        }
        if (!(key & KEY_B)) {
            draw_hex(20, 10, 1, 0xFFFF);
        } 
        if (!(key & KEY_SELECT)) {
            draw_hex(30, 10, 2, 0xFFFF);
        }
        if (!(key & KEY_START)) {
            draw_hex(40, 10, 3, 0xFFFF);
        }
        if (!(key & KEY_RIGHT)) {
            draw_hex(50, 10, 4, 0xFFFF);
        }
        if (!(key & KEY_LEFT)) {
            draw_hex(60, 10, 5, 0xFFFF);
        }
        if (!(key & KEY_RIGHT)) {
            draw_hex(70, 10, 6, 0xFFFF);
        }
        if (!(key & KEY_UP)) {
            draw_hex(80, 10, 7, 0xFFFF);
        }
        if (!(key & KEY_DOWN)) {
            draw_hex(90, 10, 8, 0xFFFF);
        }
        if (!(key & KEY_R)) {
            draw_hex(100, 10, 9, 0xFFFF);
        }
        if (!(key & KEY_L)) {
            draw_hex(110, 10, 10, 0xFFFF);
        }
    } 
}
font.h
#ifndef FONT_H
#define FONT_H

typedef unsigned char  uint8_t;

extern const uint8_t font[16][8];

#endif
font.c
font.c
#include "font.h"

const uint8_t font[16][8] = {
// 0
    {0b00111100,  //   ████
     0b01100110,  // ██    ██
     0b01100110,  // ██    ██
     0b01100110,  // ██    ██
     0b01100110,  // ██    ██
     0b01100110,  // ██    ██
     0b00111100,  //   ████
     0b00000000}, // 

    // 1
    {0b00011000,  //    ██
     0b00111000,  //   ███
     0b00011000,  //    ██
     0b00011000,  //    ██
     0b00011000,  //    ██
     0b00011000,  //    ██
     0b00111100,  //   ████
     0b00000000}, // 
    // 2
    {0b00111100,  //  ██████
     0b01100110,  // ██    ██
     0b00000110,  //      ██
     0b00011100,  //    ██
     0b00110000,  //   ██
     0b01100000,  //  ██
     0b01111110,  // ████████
     0b00000000}, //
    // 3
    {0b00111100,  //  ██████
     0b01100110,  // ██    ██
     0b00000110,  //      ██
     0b00011100,  //    ███
     0b00000110,  //      ██
     0b01100110,  // ██    ██
     0b00111100,  //  ██████
     0b00000000}, // 
// 4
    {0b00001100,  //     ██
     0b00011100,  //    ███
     0b00111100,  //   ████
     0b01101100,  //  ██ ██
     0b01111110,  // ████████
     0b00001100,  //     ██
     0b00001100,  //     ██
     0b00000000}, // 
    
    // 5
    {0b01111110,  // ████████
     0b01100000,  // ██
     0b01111100,  // ██████
     0b00000110,  //       ██
     0b00000110,  //       ██
     0b01100110,  // ██   ██
     0b00111100,  //  ██████
     0b00000000}, // 
    
    // 6
    {0b00011100,  //    ████
     0b00110000,  //   ██
     0b01100000,  //  ██
     0b01111100,  // ██████
     0b01100110,  // ██    ██
     0b01100110,  // ██    ██
     0b00111100,  //  ██████
     0b00000000}, // 
    
    // 7
    {0b01111110,  // ████████
     0b00000110,  //      ██
     0b00001100,  //     ██
     0b00011000,  //    ██
     0b00110000,  //   ██
     0b00110000,  //   ██
     0b00110000,  //   ██
     0b00000000}, //
// 8
    {0b00111100,  //  ██████
     0b01100110,  // ██    ██
     0b01100110,  // ██    ██
     0b00111100,  //  ██████
     0b01100110,  // ██    ██
     0b01100110,  // ██    ██
     0b00111100,  //  ██████
     0b00000000}, // 
    
    // 9
    {0b00111100,  //  ██████
     0b01100110,  // ██    ██
     0b01100110,  // ██    ██
     0b00111110,  //  ██████
     0b00000110,  //      ██
     0b00001100,  //     ██
     0b00111000,  //  ████
     0b00000000}, // 
    
    // A
    {0b00011000,  //   ██
     0b00111100,  //  ████
     0b01100110,  // ██  ██
     0b01100110,  // ██  ██
     0b01111110,  // ██████
     0b01100110,  // ██  ██
     0b01100110,  // ██  ██
     0b00000000}, // 
    
    // B
    {0b01111100,  // █████
     0b01100110,  // ██  ██
     0b01100110,  // ██  ██
     0b01111100,  // █████
     0b01100110,  // ██  ██
     0b01100110,  // ██  ██
     0b01111100,  // █████
     0b00000000}, // 
    
    // C
    {0b00111100,  //  ██████
     0b01100110,  // ██    ██
     0b01100000,  // ██
     0b01100000,  // ██
     0b01100000,  // ██
     0b01100110,  // ██    ██
     0b00111100,  //  ██████
     0b00000000}, //
// D
    {0b01111000,  // █████
     0b01101100,  // ██   ██
     0b01100110,  // ██    ██
     0b01100110,  // ██    ██
     0b01100110,  // ██    ██
     0b01101100,  // ██  ██
     0b01111000,  // █████
     0b00000000}, // 
    
    // E
    {0b01111110,  // ████████
     0b01100000,  // ██
     0b01100000,  // ██
     0b01111100,  // ██████
     0b01100000,  // ██
     0b01100000,  // ██
     0b01111110,  // ████████
     0b00000000}, // 
    
    // F
    {0b01111110,  // ████████
     0b01100000,  // ██
     0b01100000,  // ██
     0b01111100,  // ██████
     0b01100000,  // ██
     0b01100000,  // ██
     0b01100000,  // ██
     0b00000000}, //
};
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?