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?

PIC16F18326とSDカードで音楽再生(8bit, 24kHz)(FAT)

Posted at

概要

PIC16F18326を使いました.クロックは32MHzです.

SDカードにあるPCMデータをMCCのFatFsで読み出して,PWM出力しました.
SDカードにファイルシステムを使ってアクセスしているので,音声データの書き込みがPCでちゃちゃっとできます(超便利).

音質は8bit, 24kHz, モノラルです.PICの性能的には分解能はもっと上げられますが,10bitとか9bitとかキリが悪いので8bitにしました.

僕は今までレジスタこちょこちょ派で,MCCなんか使ったら面白くないじゃん!と思っていたのですが,短時間でこんなに複雑なことができたので大満足です.

MCCの操作

MCCはClassicとMelodyがありますが,現時点(2024/08/21)ではMelodyにはSDカードのライブラリがない(?)のでClassicにします.

System Module

まずはじめに,System Moduleのタブで,クロックを32MHzに,Clock Dividerを1にします.

Timer 0

デューティ比を更新する割り込みを作るためにTimer 0を使います.
PWMのDuty値は,サンプリング周波数が24kHzなので41.66666666666[us]ごとに更新します.
説明がめんどくさいのでスクショはこんな感じです.
スクリーンショット 2024-08-21 105829.png

Timer 2

PWM用のTimer 2です.
スクリーンショット 2024-08-21 110825.png

PWM

PWMです.キャリア周波数が125kHzなので,人間には聴こえないはずです.
スクリーンショット 2024-08-21 110938.png

SDCard

CDとWPはDisableしました.
スクリーンショット 2024-08-21 111058.png

FatFS

いらない機能を削除すれば,プログラムメモリが節約できます(f_writeなどは今回必要ない).
スクリーンショット 2024-08-21 111307.png
スクリーンショット 2024-08-21 111348.png
これ以外はDefaultのままです.

PPS

SDO1,PWM5,CSは手動で設定しました.
image.png

設定は終わったのでGenerateします.

ユーザーコード

SDカード内のmusic.rawを読み込んで再生します.music.rawの作り方は後で説明します.
このプログラムは,常にBUF_SIZE分だけデータを先読みしながら,データ読み出しと音声再生を並列処理しています.

main.c
#include "mcc_generated_files/mcc.h"
#define BUF_SIZE 256

/*
                         Main application
 */

uint8_t buf[2][BUF_SIZE];
uint8_t buf_id=0;
uint16_t ptr=0;
bool request=false;

void tmr0_isr() {
    if(ptr == 0) {
        request = true;    // メインルーチンにバッファへの読み込みをリクエスト
    }
    
    PWM5_LoadDutyValue(buf[buf_id][ptr++]);    // 読み込んだデータでデューティー比を更新
    
    if(ptr == BUF_SIZE) {    // バッファの末尾に達したら,バッファを切り替え
        ptr = 0;
        buf_id = buf_id+1 >= 2 ? 0 : buf_id+1;
    }
}

static FATFS drive;
static FIL file;

void main(void)
{
    // initialize the device
    SYSTEM_Initialize();

    // When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits
    // Use the following macros to:

    // Enable the Global Interrupts
    INTERRUPT_GlobalInterruptEnable();

    // Enable the Peripheral Interrupts
    INTERRUPT_PeripheralInterruptEnable();

    // Disable the Global Interrupts
    //INTERRUPT_GlobalInterruptDisable();

    // Disable the Peripheral Interrupts
    //INTERRUPT_PeripheralInterruptDisable();
    
    
    f_mount(&drive, "0:", 1);
    if(f_open(&file, "music.raw", FA_READ) != FR_OK) {
        f_mount(NULL, "0:", 0);
        while(1);
    }
    
    f_read(&file, buf[0], BUF_SIZE, NULL);
    
    TMR0_StartTimer();
    TMR0_SetInterruptHandler(tmr0_isr);
    TMR2_StartTimer();
    PWM5_LoadDutyValue(0);

    uint16_t actual_len, len;
    FRESULT res;
    
    while (1)
    {
        // Add your application code
        if(request) {    // 割り込みルーチンからのリクエストがあったら,つぎのバッファにデータを準備
            request = false;
            len = 0;
            
            do {
                res = f_read(&file, &buf[buf_id+1 >= 2 ? 0 : buf_id+1][len], BUF_SIZE-len, &actual_len);
                len += actual_len;
                
                if(actual_len == 0 || res != FR_OK) {
                    TMR0_StopTimer();
                    PWM5_LoadDutyValue(0);
                    f_close(&file);
                    f_mount(NULL, "0:", 0);
                    while(1);
                }
            } while(len != BUF_SIZE);
        }
    }
}
/**
 End of File
*/

メモリ使用量はこんな感じです.
image.png

音声データの作り方

ffmpegで一発

ffmpeg -i "任意の音楽ファイル" -ac 1 -ar 24000 -acodec pcm_u8 -f u8 music.raw

再生

YouTube人生初投稿!

SDカードの電源は3.3Vです

トランジスタ1個でアンプのようなものも作りました.

おわりに

$ \mathrm{I^2C} $のEEPROM(24LC512)で音楽再生をやったこともありますが,容量的に再生できるのが数秒程度でした.今回は,16GBのSDカードを使ったので,約715828秒,11930分,199時間,8.29日の音楽を流せます!🎉🎉🎉

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?