Closed modi12jin closed 2 years ago
is this for the plus module? I see you are using parallel bus for the display.
hello @modi12jin I just got the Plus module, but I have trouble programming it with Platformio. Which IDE are you using and which board should be selected?
hello @modi12jin I just got the Plus module, but I have trouble programming it with Platformio. Which IDE are you using and which board should be selected?
Arduino IDE 2.0
@fbiego I saw your SC01 PLIUS video on youtube very smooth
SC01 PLUS for testing I2S and SDIO
//https://github.com/schreibfaul1/ESP32-audioI2S
#include "Arduino.h"
#include "WiFiMulti.h"
#include "Audio.h"
#include "SD_MMC.h"
#include "FS.h"
#define SD_CS 41
#define SDMMC_CMD 40
#define SDMMC_CLK 39
#define SDMMC_D0 38
#define I2S_DOUT 37
#define I2S_BCLK 36
#define I2S_LRC 35
Audio audio;
// WiFiMulti wifiMulti;
// String ssid = "MERCURY_2FF2";
// String password = "1234567890";
void setup() {
Serial.begin(115200);
pinMode(SD_CS, OUTPUT);
digitalWrite(SD_CS, HIGH);
SD_MMC.setPins(SDMMC_CLK,SDMMC_CMD,SDMMC_D0);
SD_MMC.begin("/root",true);
// WiFi.mode(WIFI_STA);
// wifiMulti.addAP(ssid.c_str(), password.c_str());
// wifiMulti.run();
// if(WiFi.status() != WL_CONNECTED){
// WiFi.disconnect(true);
// wifiMulti.run();
// }
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(21); // 0...21
audio.connecttoFS(SD_MMC, "/320k_test.mp3");
//audio.connecttohost("http://music.163.com/song/media/outer/url?id=1873321491.mp3"); // 128k mp3
}
void loop()
{
audio.loop();
}
SC01 PLUS Specification Manual
Official Online Tool
@fbiego I believe it would be cool to add video playback inside your code
SC01-plus MiniTV(ZX3D50CE02S Alias SC01-plus)
https://www.instructables.com/Mini-Retro-TV/
https://github.com/moononournation/MiniTV
/***
* Required libraries:
* https://github.com/lovyan03/LovyanGFX.git
* https://github.com/pschatzmann/arduino-libhelix.git
* https://github.com/bitbank2/JPEGDEC.git
*/
// auto fall back to MP3 if AAC file not available
#define AAC_FILENAME "/44100.aac"
#define MP3_FILENAME "/44100.mp3"
#define MJPEG_FILENAME "/480_12fps.mjpeg"
#define FPS 12
#define MJPEG_BUFFER_SIZE (480 * 270 * 2 / 10)
#define AUDIOASSIGNCORE 1
#define DECODEASSIGNCORE 1
#define DRAWASSIGNCORE 0
#define LGFX_USE_V1
#include <WiFi.h>
#include <FS.h>
#include <SD_MMC.h>
#include <LovyanGFX.hpp>
#define SD_CS 41
#define SDMMC_CMD 40
#define SDMMC_CLK 39
#define SDMMC_D0 38
class LGFX : public lgfx::LGFX_Device
{
lgfx::Panel_ST7796 _panel_instance;
lgfx::Bus_Parallel8 _bus_instance;
lgfx::Light_PWM _light_instance;
lgfx::Touch_FT5x06 _touch_instance;
public:
LGFX(void)
{
{
auto cfg = _bus_instance.config();
cfg.port = 0;
cfg.freq_write = 40000000;
cfg.pin_wr = 47; // WR を接続しているピン番号
cfg.pin_rd = -1; // RD を接続しているピン番号
cfg.pin_rs = 0; // RS(D/C)を接続しているピン番号
cfg.pin_d0 = 9; // D0を接続しているピン番号
cfg.pin_d1 = 46; // D1を接続しているピン番号
cfg.pin_d2 = 3; // D2を接続しているピン番号
cfg.pin_d3 = 8; // D3を接続しているピン番号
cfg.pin_d4 = 18; // D4を接続しているピン番号
cfg.pin_d5 = 17; // D5を接続しているピン番号
cfg.pin_d6 = 16; // D6を接続しているピン番号
cfg.pin_d7 = 15; // D7を接続しているピン番号
_bus_instance.config(cfg); // 設定値をバスに反映します。
_panel_instance.setBus(&_bus_instance); // バスをパネルにセットします。
}
{ // 表示パネル制御の設定を行います。
auto cfg = _panel_instance.config(); // 表示パネル設定用の構造体を取得します。
cfg.pin_cs = -1; // CSが接続されているピン番号 (-1 = disable)
cfg.pin_rst = 4; // RSTが接続されているピン番号 (-1 = disable)
cfg.pin_busy = -1; // BUSYが接続されているピン番号 (-1 = disable)
// ※ 以下の設定値はパネル毎に一般的な初期値が設定さ BUSYが接続されているピン番号 (-1 = disable)れていますので、不明な項目はコメントアウトして試してみてください。
cfg.memory_width = 320; // ドライバICがサポートしている最大の幅
cfg.memory_height = 480; // ドライバICがサポートしている最大の高さ
cfg.panel_width = 320; // 実際に表示可能な幅
cfg.panel_height = 480; // 実際に表示可能な高さ
cfg.offset_x = 0; // パネルのX方向オフセット量
cfg.offset_y = 0; // パネルのY方向オフセット量
cfg.offset_rotation = 1; //值在旋转方向的偏移0~7(4~7是倒置的)
cfg.dummy_read_pixel = 8; // 在读取像素之前读取的虚拟位数
cfg.dummy_read_bits = 1; // 读取像素以外的数据之前的虚拟读取位数
cfg.readable = false; // 如果可以读取数据,则设置为 true
cfg.invert = true; // 如果面板的明暗反转,则设置为 true
cfg.rgb_order = false; // 如果面板的红色和蓝色被交换,则设置为 true
cfg.dlen_16bit = false; // 对于以 16 位单位发送数据长度的面板,设置为 true
cfg.bus_shared = false; // 如果总线与 SD 卡共享,则设置为 true(使用 drawJpgFile 等执行总线控制)
_panel_instance.config(cfg);
}
{ // バックライト制御の設定を行います。(必要なければ削除)
auto cfg = _light_instance.config(); // バックライト設定用の構造体を取得します。
cfg.pin_bl = 45; // バックライトが接続されているピン番号
cfg.invert = false; // バックライトの輝度を反転させる場合 true
cfg.freq = 44100; // バックライトのPWM周波数
cfg.pwm_channel = 1; // 使用するPWMのチャンネル番号
_light_instance.config(cfg);
_panel_instance.setLight(&_light_instance); // バックライトをパネルにセットします。
}
{ // タッチスクリーン制御の設定を行います。(必要なければ削除)
auto cfg = _touch_instance.config();
cfg.x_min = 0; // タッチスクリーンから得られる最小のX値(生の値)
cfg.x_max = 319; // タッチスクリーンから得られる最大のX値(生の値)
cfg.y_min = 0; // タッチスクリーンから得られる最小のY値(生の値)
cfg.y_max = 479; // タッチスクリーンから得られる最大のY値(生の値)
cfg.pin_int = 7; // INTが接続されているピン番号
cfg.bus_shared = false; // 如果您使用与屏幕相同的总线,则设置为 true
cfg.offset_rotation = 0;// 显示和触摸方向不匹配时的调整 设置为 0 到 7 的值
// I2C接続の場合
cfg.i2c_port = 0; // 使用するI2Cを選択 (0 or 1)
cfg.i2c_addr = 0x38; // I2Cデバイスアドレス番号
cfg.pin_sda = 6; // SDAが接続されているピン番号
cfg.pin_scl = 5; // SCLが接続されているピン番号
cfg.freq = 400000; // I2Cクロックを設定
_touch_instance.config(cfg);
_panel_instance.setTouch(&_touch_instance); // タッチスクリーンをパネルにセットします。
}
setPanel(&_panel_instance); // 使用するパネルをセットします。
}
};
LGFX tft;
/* variables */
static int next_frame = 0;
static int skipped_frames = 0;
static unsigned long start_ms, curr_ms, next_frame_ms;
/* audio */
#include "esp32_audio_task.h"
/* MJPEG Video */
#include "mjpeg_decode_draw_task.h"
// pixel drawing callback
static int drawMCU(JPEGDRAW *pDraw) {
if(tft.getStartCount()==0)
{
tft.endWrite();
}
tft.pushImageDMA(pDraw->x, pDraw->y, pDraw->iWidth, pDraw->iHeight,(lgfx::rgb565_t *)pDraw->pPixels);
return 1;
} /* drawMCU() */
void setup() {
disableCore0WDT();
WiFi.mode(WIFI_OFF);
Serial.begin(115200);
// Init Display
tft.init();
tft.initDMA();
tft.startWrite();
tft.fillScreen(TFT_BLACK);
esp_err_t ret_val = i2s_init(I2S_NUM_0, 44100, -1 /* MCLK */, 36 /* SCLK */, 35 /* LRCK */, 37 /* DOUT */, -1 /* DIN */);
if (ret_val != ESP_OK) {
Serial.printf("i2s_init failed: %d\n", ret_val);
}
i2s_zero_dma_buffer(I2S_NUM_0);
pinMode(SD_CS, OUTPUT);
digitalWrite(SD_CS, HIGH);
SD_MMC.setPins(SDMMC_CLK, SDMMC_CMD, SDMMC_D0);
if (!SD_MMC.begin("/root", true))/* 1-bit SD bus mode */
{
Serial.println("ERROR: File system mount failed!");
tft.println("ERROR: File system mount failed!");
} else {
bool aac_file_available = false;
File aFile = SD_MMC.open(AAC_FILENAME);
if (aFile) {
aac_file_available = true;
} else {
aFile = SD_MMC.open(MP3_FILENAME);
}
if (!aFile || aFile.isDirectory()) {
Serial.println("ERROR: Failed to open " AAC_FILENAME " or " MP3_FILENAME " file for reading");
tft.println("ERROR: Failed to open " AAC_FILENAME " or " MP3_FILENAME " file for reading");
} else {
File vFile = SD_MMC.open(MJPEG_FILENAME);
if (!vFile || vFile.isDirectory()) {
Serial.println("ERROR: Failed to open " MJPEG_FILENAME " file for reading");
tft.println("ERROR: Failed to open " MJPEG_FILENAME " file for reading");
} else {
mjpeg_setup(&vFile, MJPEG_BUFFER_SIZE, drawMCU,
false /* useBigEndian */, DECODEASSIGNCORE, DRAWASSIGNCORE);
BaseType_t ret_val;
if (aac_file_available) {
ret_val = aac_player_task_start(&aFile, AUDIOASSIGNCORE);
} else {
ret_val = mp3_player_task_start(&aFile, AUDIOASSIGNCORE);
}
if (ret_val != pdPASS) {
Serial.printf("Audio player task start failed: %d\n", ret_val);
tft.printf("Audio player task start failed: %d\n", ret_val);
}
start_ms = millis();
curr_ms = millis();
next_frame_ms = start_ms + (++next_frame * 1000 / FPS / 2);
while (vFile.available() && mjpeg_read_frame()) // Read video
{
total_read_video_ms += millis() - curr_ms;
curr_ms = millis();
if (millis() < next_frame_ms) // check show frame or skip frame
{
// Play video
mjpeg_draw_frame();
total_decode_video_ms += millis() - curr_ms;
curr_ms = millis();
} else {
++skipped_frames;
//Serial.println("Skip frame");
}
while (millis() < next_frame_ms) {
vTaskDelay(pdMS_TO_TICKS(1));
}
curr_ms = millis();
next_frame_ms = start_ms + (++next_frame * 1000 / FPS);
}
Serial.println("AV end");
vFile.close();
aFile.close();
}
}
}
}
void loop() {
}
Great, I will check that out
@fbiego With LovyanGFX you have better framerates