zoologist 发表于 2021-4-19 20:21:02

FireBeetle 更大的存储空间用于播放音频

前面的文章介绍了 DAC 方式播放和用更高精度的 PWM 方式直接播放音频文件,但是很明显我们遇到了的2个问题:1.      1.存储空间有限,APP中最大只能存放2.7MB的音频;2.      2.每次都需要手工将数据转化为 .h ,比较麻烦。
这次就介绍如何在 FireBeetle上使用更大的空间。从介绍中可以看到FireBeetleFlash 为16MB,但是 APP 最大只能用到3MB,余下的空间要么分配给 SPIFFS,要么分给 FATFS。
SPIFFS 和 FATFS 都是一种文件系统。其中SPIFFS是一个用于SPI NOR flash 设备的嵌入式文件系统,支持磨损均衡、文件系统一致性检查等功能【参考1】。同样的 FATFS也是一种文件系统【参考2】。很明显ESP32 上我们可以使用更大的空间,因此这里尝试使用FATSFS来存储音频文件。对于 ESP32 来说,每次上传的 APP 和 FATFS 是分开的。比如,编译之后生成了一个3MB 的APP, 那么上传时只会烧写更新3MB APP那一段的SPINOR中的内容,余下的部分不会改变(加上压缩以及快速的串口通讯,我们并不会感觉上传太慢)。因此,我们还需要一个额外的工具来完成上传 FATFS 的部分。这个工具就是arduinoesp32fs 插件,这个插件能将文件传输到ESP32的SPIFFS,LittleFS 或者FatFS分区上,项目地址如下:https://github.com/lorol/arduino-esp32fs-plugin下载到编译好的文件是一个 JAR文件。

安装方法是在你 Arduino.exe 的目录中,Tools下创建ESP32FS/Tool 目录,然后将上面这个文件放置进去:

重启 Arduino 之后在 Tools 菜单中会出现 “ESP32Sketch Data Upload”的选项。

为了给 FATFS 分区上传,我们还需要2个额外的工具 mklittlefs.exe 和 mkfatfs.exe。这两个工具需要放在C:\Users\用户名\AppData\Local\Arduino15\packages\firebeetle32\hardware\esp32\0.1.1\tools目录下。上面准备妥当之后,先编写一个测试程序。这个程序会列出当前 FATFS 上面的文件名称。
#include "FS.h"
#include "FFat.h"

void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
    Serial.printf("Listing directory: %s\r\n", dirname);

    File root = fs.open(dirname);
    if(!root){
      Serial.println("- failed to open directory");
      return;
    }
    if(!root.isDirectory()){
      Serial.println(" - not a directory");
      return;
    }

    File file = root.openNextFile();
    while(file){
      if(file.isDirectory()){
            Serial.print("DIR : ");
            Serial.println(file.name());
            if(levels){
                listDir(fs, file.name(), levels -1);
            }
      } else {
            Serial.print("FILE: ");
            Serial.print(file.name());
            Serial.print("\tSIZE: ");
            Serial.println(file.size());
      }
      file = root.openNextFile();
    }

   
}

void setup() {
Serial.begin(115200);
if(!FFat.begin()){
      Serial.println("FFat Mount Failed");
      return;
}
    Serial.printf("Total space: %10u\n", FFat.totalBytes());
    Serial.printf("Free space: %10u\n", FFat.freeBytes());
   
}

void loop() {
    listDir(FFat, "/", 0);
    delay(5000);
}
此外,我们还要在程序目录下创建一个 data 目录,然后将3支歌曲的文件放在里面。
直接使用菜单上传FATFS分区。

选择 FATFS:
看到下面的字样就表示已经成功:
接下来,像普通 Arduino 代码一样上传我们的程序,打开串口就能看到结果:
有了上面的代码,我们可以很容易编写出来播放代码: #include "FS.h"
#include "FFat.h"

#include "data\1990.h"
#include "soc/sens_reg.h"// For dacWrite() patch, TEB Sep-16-2019

void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
    Serial.printf("Listing directory: %s\r\n", dirname);

    File root = fs.open(dirname);
    if(!root){
      Serial.println("- failed to open directory");
      return;
    }
    if(!root.isDirectory()){
      Serial.println(" - not a directory");
      return;
    }

    File file = root.openNextFile();
    while(file){
      if(file.isDirectory()){
            Serial.print("DIR : ");
            Serial.println(file.name());
            if(levels){
                listDir(fs, file.name(), levels -1);
            }
      } else {
            Serial.print("FILE: ");
            Serial.print(file.name());
            Serial.print("\tSIZE: ");
            Serial.println(file.size());
      }
      file = root.openNextFile();
    }

   
}

void playFile(fs::FS &fs, const char * path){
    Serial.printf("Playing file: %s\r\n", path);

    File file = fs.open(path);
    if(!file){
      Serial.println("- failed to open file for reading");
      return;
    }

    uint8_t buffer;
    size_t bytessend;
    while(file.available()){
      bytessend=file.read(buffer, 1024*4);
      for (int i=0;i<1024*4;i++) {
            CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN1_M);
            SET_PERI_REG_BITS(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_DAC, buffer, RTC_IO_PDAC1_DAC_S);
            SET_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE);
            ets_delay_us(125);
      }
    }
    file.close();
}
void setup() {
Serial.begin(115200);
if(!FFat.begin()){
      Serial.println("FFat Mount Failed");
      return;
}
    Serial.printf("Total space: %10u\n", FFat.totalBytes());
    Serial.printf("Free space: %10u\n", FFat.freeBytes());
   
    listDir(FFat, "/", 0);
}

void loop() {
    playFile(FFat, "/1st.wav");
    playFile(FFat, "/10years.wav");
    playFile(FFat, "/1990.wav");
}

参考:1.   https://docs.espressif.com/projects/esp-idf/zh_CN/release-v4.1/api-reference/storage/spiffs.html2.   https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/storage/fatfs.html











pATAq 发表于 2021-4-20 00:47:54

很好的帖子,学习了!

zoologist 发表于 2021-6-13 17:06:40

本问题到的 mklittlefs.exe 和 mkfatfs.exe





页: [1]
查看完整版本: FireBeetle 更大的存储空间用于播放音频