[MacOS] Apple Siliconで内部音声付き画面収録

[M1 Mac, Ventura 13.0]

MacOSではデフォルトで内部音声付き画面収録ができません。

“BlackHole”という仮想オーディオドライバを導入すると内部音声も収録できるようになります。このドライバのソースコードはGitHubで公開されています。今回はビルド済みバイナリをダウンロードして導入しました(メールアドレスの登録が必要)。

MacOSのユーティリティ – Audio MIDI設定で以下のように設定します。

入力(マイクの記号)はBlackHole 2chに設定し、出力(スピーカーの記号)は複数出力装置でBlackHole 2chとMacのオーディオ装置をチェックします。左下の歯車ボタンで入力と出力を適切に設定しないとうまくできないので要注意です。

2023/3/31追記
現在のBlackHoleはビルド済バイナリのダウンロードでは$5以上の寄付が必須になっている。Homebrewからもインストール出来るが、M1 Macでは30分経過したあたりから音が割れ出して最終的には無音になる。仕方ないのでIntel Macで収録している。

[MacOS] Makefileを常にVSCodeで開く : SwiftDefaultApps

SwiftDefaultAppsでテキストエディットに関連するファイルを全てVSCodeで開くように変更しました。

Applicationsタブでテキストエディットの関連ファイルとしてチェックが入っているファイルタイプについて左隣のUniform Type Identifiers(UTI)タブでVSCodeに設定しました。

これでMakefileをダウンロードする度に右クリックメニューで関連付けを変更しなくて済みます。ちなみにMakefileのUTIはpublic.dataです。テキストエディットが起動することは今後一切ありません。

拡張子のないファイルについてはこの方法で解決できます。大げさですが長年の懸案からこれで解放されそうです。

ネットにはMakefileに関するこの種の情報が見当たりませんでした。こういう細かいところでの使いづらさに耐えきれず、皆さんLinuxへ行ってしまうのでしょうか。

私もほとほとあきれているクチですが、まだしばらくMacで粘ってみます。

[MacOS] Tokyo Cabinetの削除コマンド

インストールはしたものの私には不要だったので、以下コマンドで削除しました。下4つ以外は一括削除できます。

rm /usr/local/include/tcutil.h
rm /usr/local/include/tchdb.h
rm /usr/local/include/tcbdb.h
rm /usr/local/include/tcfdb.h
rm /usr/local/include/tctdb.h
rm /usr/local/include/tcadb.h
rm /usr/local/lib/libtokyocabinet.a
rm /usr/local/lib/libtokyocabinet.so.x.y.z
rm /usr/local/lib/libtokyocabinet.so.x
rm /usr/local/lib/libtokyocabinet.so
rm /usr/local/lib/pkgconfig/tokyocabinet.pc
rm /usr/local/bin/tcutest
rm /usr/local/bin/tcumttest
rm /usr/local/bin/tcucodec
rm /usr/local/bin/tchtest
rm /usr/local/bin/tchmttest
rm /usr/local/bin/tchmgr
rm /usr/local/bin/tcbmgr
rm /usr/local/bin/tcbtest
rm /usr/local/bin/tcbmttest
rm /usr/local/bin/tcftest
rm /usr/local/bin/tcfmttest
rm /usr/local/bin/tcfmgr
rm /usr/local/bin/tcttest
rm /usr/local/bin/tctmttest
rm /usr/local/bin/tctmgr
rm /usr/local/bin/tcatest
rm /usr/local/bin/tcamttest
rm /usr/local/bin/tcamgr
sudo rm /usr/local/libexec/tcawmgr.cgi
sudo rm -r /usr/local/share/tokyocabinet/
sudo rm -r /usr/local/man/man1/
sudo rm -r /usr/local/man/man3/

[LLDB] アセンブリ言語の行にBreakpointを設定する

[M1 Mac, Big Sur 11.6.8, clang 13.0.0, NO IDE]

C言語コードの行単位ではレジスタ値やメモリ値の詳細が追えないので、アセンブリ言語の行単位で追跡する方法を模索しました。

GDBは不可、LLDBでは可能でした。ただし最初にrunコマンドで空実行させないと有効なBreakpointが設定できません。

GDBが仕様及び酷いバグでIntel Macでもまともに使えない状態になっていますが、LLDBのこの程度の不具合ならかわいいものです。

ちなみにGDB導入についてはIntel MacにMacPortsでインストール、ggdbファイルにコード署名、SIP(System Integrity Protection)を–without debugオプションで限定的に解除しても、結局バグに阻まれました。なおApple Siliconには今のところビルド済みファイルは提供されていません。

GCC、GDB共にソースコードからのビルドもまともにできないですし、GNUはMacを軽視しているように思います。だからこそAppleはclangやLLDBの開発に注力しているのでしょう。

LLDBではなんとかできたものの、nextコマンドを使えずアセンブリ言語コード各行をBreakpointとして設定する必要があるのでかなり面倒です。

とりあえずログを載せておきます。

bin $ lldb test
(lldb) target create "test"
Current executable set to /test' (arm64).
(lldb) disass -n main
test`main:
test[0x100003e48] <+0>:   sub    sp, sp, #0x60             ; =0x60 
test[0x100003e4c] <+4>:   stp    x29, x30, [sp, #0x50]
test[0x100003e50] <+8>:   mov    w8, #0x0
test[0x100003e54] <+12>:  str    w8, [sp, #0x2c]
test[0x100003e58] <+16>:  str    wzr, [sp, #0x4c]
test[0x100003e5c] <+20>:  mov    w8, #0x3e8
test[0x100003e60] <+24>:  str    w8, [sp, #0x48]
test[0x100003e64] <+28>:  adrp   x8, 0
test[0x100003e68] <+32>:  add    x8, x8, #0xf50            ; =0xf50 
test[0x100003e6c] <+36>:  ldr    w9, [x8]
test[0x100003e70] <+40>:  add    x10, sp, #0x40            ; =0x40 
test[0x100003e74] <+44>:  str    x10, [sp, #0x10]
test[0x100003e78] <+48>:  str    w9, [sp, #0x40]
test[0x100003e7c] <+52>:  ldrh   w8, [x8, #0x4]
test[0x100003e80] <+56>:  strh   w8, [sp, #0x44]
test[0x100003e84] <+60>:  add    x8, sp, #0x38             ; =0x38 
test[0x100003e88] <+64>:  str    x8, [sp, #0x18]
test[0x100003e8c] <+68>:  mov    x8, #0x797a
test[0x100003e90] <+72>:  movk   x8, #0x78, lsl #16
test[0x100003e94] <+76>:  str    x8, [sp, #0x38]
test[0x100003e98] <+80>:  add    x8, sp, #0x30             ; =0x30 
test[0x100003e9c] <+84>:  str    x8, [sp, #0x20]
test[0x100003ea0] <+88>:  adrp   x8, 0
test[0x100003ea4] <+92>:  add    x8, x8, #0xf56            ; =0xf56 
test[0x100003ea8] <+96>:  str    x8, [sp, #0x30]
test[0x100003eac] <+100>: ldr    w9, [sp, #0x48]
test[0x100003eb0] <+104>: mov    x8, x9
test[0x100003eb4] <+108>: adrp   x0, 0
test[0x100003eb8] <+112>: add    x0, x0, #0xf5a            ; =0xf5a 
test[0x100003ebc] <+116>: mov    x9, sp
test[0x100003ec0] <+120>: str    x8, [x9]
test[0x100003ec4] <+124>: bl     0x100003f20               ; symbol stub for: printf
test[0x100003ec8] <+128>: ldr    x8, [sp, #0x10]
test[0x100003ecc] <+132>: adrp   x0, 0
test[0x100003ed0] <+136>: add    x0, x0, #0xf61            ; =0xf61 
test[0x100003ed4] <+140>: mov    x9, sp
test[0x100003ed8] <+144>: str    x8, [x9]
test[0x100003edc] <+148>: bl     0x100003f20               ; symbol stub for: printf
test[0x100003ee0] <+152>: ldr    x8, [sp, #0x18]
test[0x100003ee4] <+156>: adrp   x0, 0
test[0x100003ee8] <+160>: add    x0, x0, #0xf68            ; =0xf68 
test[0x100003eec] <+164>: mov    x9, sp
test[0x100003ef0] <+168>: str    x8, [x9]
test[0x100003ef4] <+172>: bl     0x100003f20               ; symbol stub for: printf
test[0x100003ef8] <+176>: ldr    x8, [sp, #0x20]
test[0x100003efc] <+180>: adrp   x0, 0
test[0x100003f00] <+184>: add    x0, x0, #0xf73            ; =0xf73 
test[0x100003f04] <+188>: mov    x9, sp
test[0x100003f08] <+192>: str    x8, [x9]
test[0x100003f0c] <+196>: bl     0x100003f20               ; symbol stub for: printf
test[0x100003f10] <+200>: ldr    w0, [sp, #0x2c]
test[0x100003f14] <+204>: ldp    x29, x30, [sp, #0x50]
test[0x100003f18] <+208>: add    sp, sp, #0x60             ; =0x60 
test[0x100003f1c] <+212>: ret    
(lldb) run
Process 21720 launched: '/test' (arm64)
i: 1000
c: abcde
c_ptr: zyx
c_ptr2: V?
Process 21720 exited with status = 0 (0x00000000) 
(lldb) disass -n main
test`main:
0x100003e48 <+0>:   sub    sp, sp, #0x60             ; =0x60 
0x100003e4c <+4>:   stp    x29, x30, [sp, #0x50]
0x100003e50 <+8>:   mov    w8, #0x0
0x100003e54 <+12>:  str    w8, [sp, #0x2c]
0x100003e58 <+16>:  str    wzr, [sp, #0x4c]
0x100003e5c <+20>:  mov    w8, #0x3e8
0x100003e60 <+24>:  str    w8, [sp, #0x48]
0x100003e64 <+28>:  adrp   x8, 0
0x100003e68 <+32>:  add    x8, x8, #0xf50            ; =0xf50 
0x100003e6c <+36>:  ldr    w9, [x8]
0x100003e70 <+40>:  add    x10, sp, #0x40            ; =0x40 
0x100003e74 <+44>:  str    x10, [sp, #0x10]
0x100003e78 <+48>:  str    w9, [sp, #0x40]
0x100003e7c <+52>:  ldrh   w8, [x8, #0x4]
0x100003e80 <+56>:  strh   w8, [sp, #0x44]
0x100003e84 <+60>:  add    x8, sp, #0x38             ; =0x38 
0x100003e88 <+64>:  str    x8, [sp, #0x18]
0x100003e8c <+68>:  mov    x8, #0x797a
0x100003e90 <+72>:  movk   x8, #0x78, lsl #16
0x100003e94 <+76>:  str    x8, [sp, #0x38]
0x100003e98 <+80>:  add    x8, sp, #0x30             ; =0x30 
0x100003e9c <+84>:  str    x8, [sp, #0x20]
0x100003ea0 <+88>:  adrp   x8, 0
0x100003ea4 <+92>:  add    x8, x8, #0xf56            ; =0xf56 
0x100003ea8 <+96>:  str    x8, [sp, #0x30]
0x100003eac <+100>: ldr    w9, [sp, #0x48]
0x100003eb0 <+104>: mov    x8, x9
0x100003eb4 <+108>: adrp   x0, 0
0x100003eb8 <+112>: add    x0, x0, #0xf5a            ; =0xf5a 
0x100003ebc <+116>: mov    x9, sp
0x100003ec0 <+120>: str    x8, [x9]
0x100003ec4 <+124>: bl     0x100003f20               ; symbol stub for: printf
0x100003ec8 <+128>: ldr    x8, [sp, #0x10]
0x100003ecc <+132>: adrp   x0, 0
0x100003ed0 <+136>: add    x0, x0, #0xf61            ; =0xf61 
0x100003ed4 <+140>: mov    x9, sp
0x100003ed8 <+144>: str    x8, [x9]
0x100003edc <+148>: bl     0x100003f20               ; symbol stub for: printf
0x100003ee0 <+152>: ldr    x8, [sp, #0x18]
0x100003ee4 <+156>: adrp   x0, 0
0x100003ee8 <+160>: add    x0, x0, #0xf68            ; =0xf68 
0x100003eec <+164>: mov    x9, sp
0x100003ef0 <+168>: str    x8, [x9]
0x100003ef4 <+172>: bl     0x100003f20               ; symbol stub for: printf
0x100003ef8 <+176>: ldr    x8, [sp, #0x20]
0x100003efc <+180>: adrp   x0, 0
0x100003f00 <+184>: add    x0, x0, #0xf73            ; =0xf73 
0x100003f04 <+188>: mov    x9, sp
0x100003f08 <+192>: str    x8, [x9]
0x100003f0c <+196>: bl     0x100003f20               ; symbol stub for: printf
0x100003f10 <+200>: ldr    w0, [sp, #0x2c]
0x100003f14 <+204>: ldp    x29, x30, [sp, #0x50]
0x100003f18 <+208>: add    sp, sp, #0x60             ; =0x60 
0x100003f1c <+212>: ret    
(lldb) b 0x100003e48
Breakpoint 1: where = test`main at test.c:3, address = 0x0000000100003e48
(lldb) b 0x100003e4c
Breakpoint 2: where = test`main + 4 at test.c:3, address = 0x0000000100003e4c
(lldb) b 0x100003e50
Breakpoint 3: where = test`main + 8 at test.c:3, address = 0x0000000100003e50
(lldb) r
Process 22004 launched: '/test' (arm64)
Process 22004 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100003e48 test`main at test.c:3
   1   	#include <stdio.h>
   2   	
-> 3   	int main() {
   4   	    int i = 1000;
   5   	    char c[6] = {'a', 'b', 'c', 'd', 'e'};
   6   	    char* c_ptr = 'xyz';
   7   	    char* c_ptr2 = "stu";
Target 0: (test) stopped.
(lldb) next
Process 22004 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
    frame #0: 0x0000000100003e4c test`main at test.c:3
   1   	#include <stdio.h>
   2   	
-> 3   	int main() {
   4   	    int i = 1000;
   5   	    char c[6] = {'a', 'b', 'c', 'd', 'e'};
   6   	    char* c_ptr = 'xyz';
   7   	    char* c_ptr2 = "stu";
Target 0: (test) stopped.

[マイコン] AVR ATtiny13AのLED点滅が遅い

[M1 Mac, Big Sur 11.6.8, avr-gcc 9.4.0, NO IDE]

ATtiny13AにつないだLEDの点滅が設定に比べて異様に遅いので色々調べてみると、システムクロック周波数がデフォルトで8分周(8分の1)になっていました。

対策としてavrdudeでヒューズビットを変更することにより1分周に変えます。コマンドは”make fuse”です。

Makefileは以下の通りです。ヒューズビットは16進数で表記されていますが、これでは各ビットの設定がわかりにくいため2進数表記に変えています。

DEVICE     = attiny13a
CLOCK      = 9600000
PROGRAMMER = -c avrispmkII
OBJECTS    = main.o
# FUSESのシステムクロック(lfuse第4ビット[下5桁目])を8分周から1分周に変更し2進数表記にした
FUSES      = -U lfuse:w:0b01111010:m -U hfuse:w:0b11111111:m
# デフォルト FUSES      = -U lfuse:w:0x6a:m -U hfuse:w:0xff:m

AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE)
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE)

all:	main.hex

.c.o:
	$(COMPILE) -c $< -o $@

.S.o:
	$(COMPILE) -x assembler-with-cpp -c $< -o $@

.c.s:
	$(COMPILE) -S $< -o $@

flash:	all
	$(AVRDUDE) -U flash:w:main.hex:i

fuse:
	$(AVRDUDE) $(FUSES)

install: flash fuse

load: all
	bootloadHID main.hex

clean:
	rm -f main.hex main.elf $(OBJECTS)

main.elf: $(OBJECTS)
	$(COMPILE) -o main.elf $(OBJECTS)

main.hex: main.elf
	rm -f main.hex
	avr-objcopy -j .text -j .data -O ihex main.elf main.hex
	avr-size --format=avr --mcu=$(DEVICE) main.elf

disasm:	main.elf
	avr-objdump -d main.elf

cpp:
	$(COMPILE) -E main.c

# 以下追記
# cファイルからsファイル作成
asm:
	$(COMPILE) -S main.c
	
# sファイルからhexファイル作成
tar:
	$(COMPILE) -o main.o main.s -c
	$(COMPILE) -o main.elf main.o
	rm -f main.hex
	avr-objcopy -j .text -j .data -O ihex main.elf main.hex
	avr-size --format=avr --mcu=$(DEVICE) main.elf

[マイコン] Apple SiliconでAVRマイコンにhexファイルを書き込む

[M1 Mac, Big Sur 11.6.8, avr-gcc 9.4.0, NO IDE]

AVRマイコンへの書き込みではWindows環境でMicrochip Studioを使うのが定石ですが、Apple Siliconでも可能です。

一時は2014年以前のMac購入を覚悟しましたが、有志の方々が作ったApple Silicon対応コンパイラのおかげで買わずに済みました。

以下のツール等が必要になります。

1.CrossPack-AVR : Makefile作成ツール
Apple Siliconの場合 : Homebrewからインストールする。

brew install --cask crosspack-avr

Intel Macの場合 : 公式サイトからダウンロードしてインストールする。

2.avrdude : ライター操作ツール
Homebrewからインストールする。

brew install avrdude

3.avr-gcc : AVRマイコン専用コンパイラ
/usr/local/CrossPack-AVR/bin/avr-gccは古いので使用不可(Mac mini 2014以前で使用可)。”Bad CPU type in executable”というエラーが表示される。
別途、Homebrew経由でGitHubから最新版をインストールする。

brew tap osx-cross/avr
brew install avr-gcc
不適合Macでのエラー表示

書き込み手順は以下の通りです。

1.以下コマンドでプロジェクトを作成し、firmwareディレクトリへ移動する。

avr-project [プロジェクト名]

2.Makefileを書き換える。ATtiny13Aの場合は過去のMakefileをそのまま使える。書き換え方法は参考サイトを参照。

3.main.cを作成する。

4.makeコマンドでコンパイルする。

make

5.自製書き込みボードにAVRマイコンを装着する。

6.マイコンと接続したライターをMacとUSB接続する。

7.電源3V(単3×2)を自製書き込みボードに接続する。ライターがオレンジ色に点滅する場合は、電源をプラマイ逆に接続し赤色にしてから、正しい電極にする。緑色になればOK。

8.make flashコマンドでAVRマイコンへ書き込む。

make flash

9.用意しておいたブレッドボードにマイコンを装着して動作確認する。

[マイコン] AVR ATtiny13でLED点滅 C++

[Windows11, Microchip Studio 7.0.2594]

久しぶりに電子工作の世界へ戻ってきました。

2016年8月にArduino UNOを購入して以来ちょくちょくいじってきましたが、あれからラズパイやJetson Nanoなどシングルボードコンピュータを経ての復帰です。

Arduinoは教育用ということでScketchというC言語風の簡易言語を使いますが、生意気にも購入当時はつぶしが効かないからと覚える気が全くなく、すぐに飽きてしまいました。

今はC/C++がそれなりに書けるようになり、アセンブリ言語の勉強にもなるので、Arduinoではなくマイコンを使ってみることにします。何に使うつもりだったのか覚えていませんが、たまたま8pinのATtiny13Aが手元にありました。

Arduinoマイコンの自製用にAVRISP mkIIという純正ライターを購入していたため(2016年9月)、すぐに取り掛かることができました。

とはいえ久しぶりのマイコンへの書き込みですから、大分手間取りました。今後のためにチェックシートを作成するつもりです。

それからIDEの名前がAtmel StudioからMicrochip Studioに変わっていました。UIはほとんど変わっていないと思います。

とりあえずC++でLEDを点滅させました。次はアセンブリ言語で書いてみたいです。

AVRISP mkIIによるATtiny13Aへの書き込み(USB, 電源接続前)
// ATtiny13A LED点滅
#define F_CPU 9600000UL

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
	DDRB |= 0b00000001; //PB0を出力に設定
	while (1)
	{
		PORTB |= 0b00000001; //PB0をON
		_delay_ms(200); //200ms待機
		PORTB &= ~0b00000001; //PB0をOFF
		_delay_ms(200); //200ms待機
	}
}

[macOS] 拡張子とアプリの関連付け

[M1 Mac, Big Sur 11.6.8]

Finderからファイルを開こうとした場合、”情報を見る”で開くアプリを選択できますが、設定してもすぐにデフォルトに戻ってしまいます。

この仕様はWindowsに比べて著しく劣っているところでもあります。

SwiftDefaultAppsを使えばデフォルトのアプリを変えることが可能です。

なぜ標準でこの機能を搭載しないのか不思議です。