Preliminary speaker driver changes
This commit is contained in:
parent
42aa5fa315
commit
babe2f828e
54
README.md
54
README.md
@ -1,53 +1,9 @@
|
|||||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | Linux |
|
# BLK_BOX_TC
|
||||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | ----- |
|
|
||||||
|
|
||||||
# Hello World Example
|
ESP-IDF version `v5.3.2`
|
||||||
|
|
||||||
Starts a FreeRTOS task to print "Hello World".
|
Firmware for the BLK_BOX Top control board for the puzzle `PDE001`.
|
||||||
|
|
||||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
Convert audio files to 44100Hz mono signed 16 uncompressed .wav files with the following command:
|
||||||
|
```ffmpeg -i input.mp3 -ac 1 -ar 44100 -sample_fmt s16 output.wav```
|
||||||
|
|
||||||
## How to use example
|
|
||||||
|
|
||||||
Follow detailed instructions provided specifically for this example.
|
|
||||||
|
|
||||||
Select the instructions depending on Espressif chip installed on your development board:
|
|
||||||
|
|
||||||
- [ESP32 Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/index.html)
|
|
||||||
- [ESP32-S2 Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/index.html)
|
|
||||||
|
|
||||||
|
|
||||||
## Example folder contents
|
|
||||||
|
|
||||||
The project **hello_world** contains one source file in C language [hello_world_main.c](main/hello_world_main.c). The file is located in folder [main](main).
|
|
||||||
|
|
||||||
ESP-IDF projects are built using CMake. The project build configuration is contained in `CMakeLists.txt` files that provide set of directives and instructions describing the project's source files and targets (executable, library, or both).
|
|
||||||
|
|
||||||
Below is short explanation of remaining files in the project folder.
|
|
||||||
|
|
||||||
```
|
|
||||||
├── CMakeLists.txt
|
|
||||||
├── pytest_hello_world.py Python script used for automated testing
|
|
||||||
├── main
|
|
||||||
│ ├── CMakeLists.txt
|
|
||||||
│ └── hello_world_main.c
|
|
||||||
└── README.md This is the file you are currently reading
|
|
||||||
```
|
|
||||||
|
|
||||||
For more information on structure and contents of ESP-IDF projects, please refer to Section [Build System](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html) of the ESP-IDF Programming Guide.
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
* Program upload failure
|
|
||||||
|
|
||||||
* Hardware connection is not correct: run `idf.py -p PORT monitor`, and reboot your board to see if there are any output logs.
|
|
||||||
* The baud rate for downloading is too high: lower your baud rate in the `menuconfig` menu, and try again.
|
|
||||||
|
|
||||||
## Technical support and feedback
|
|
||||||
|
|
||||||
Please use the following feedback channels:
|
|
||||||
|
|
||||||
* For technical queries, go to the [esp32.com](https://esp32.com/) forum
|
|
||||||
* For a feature request or bug report, create a [GitHub issue](https://github.com/espressif/esp-idf/issues)
|
|
||||||
|
|
||||||
We will get back to you as soon as possible.
|
|
||||||
|
|||||||
@ -11,7 +11,9 @@ void init_drivers() {
|
|||||||
init_bottom_half();
|
init_bottom_half();
|
||||||
init_sd();
|
init_sd();
|
||||||
init_speaker();
|
init_speaker();
|
||||||
|
init_sseg();
|
||||||
|
init_game_timers();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Initializes I2C_NUM_0.
|
/// @brief Initializes I2C_NUM_0.
|
||||||
|
|||||||
@ -6,16 +6,16 @@
|
|||||||
// #include "drivers/tft.h"
|
// #include "drivers/tft.h"
|
||||||
// #include "drivers/wires.h"
|
// #include "drivers/wires.h"
|
||||||
// #include "drivers/sd.h"
|
// #include "drivers/sd.h"
|
||||||
// #include "drivers/game_timer.h"
|
|
||||||
// #include "drivers/speaker.h"
|
|
||||||
// #include "drivers/char_lcd.h"
|
// #include "drivers/char_lcd.h"
|
||||||
// #include "drivers/leds.h"
|
// #include "drivers/leds.h"
|
||||||
// #include "drivers/power.h"
|
// #include "drivers/power.h"
|
||||||
|
|
||||||
|
|
||||||
#include "char_lcd.h"
|
#include "char_lcd.h"
|
||||||
#include "drivers/bottom_half.h"
|
#include "bottom_half.h"
|
||||||
#include "sd.h"
|
#include "sd.h"
|
||||||
|
#include "speaker.h"
|
||||||
|
#include "game_timer.h"
|
||||||
|
|
||||||
void init_drivers();
|
void init_drivers();
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#include "bottom_half.h"
|
#include "bottom_half.h"
|
||||||
|
#include <esp_log.h>
|
||||||
|
|
||||||
static const char *TAG = "bottom_half";
|
static const char *TAG = "bottom_half";
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "driver/i2c.h"
|
#include "driver/i2c.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "esp_log.h"
|
|
||||||
|
|
||||||
#define BOTTOM_I2C_NUM I2C_NUM_0
|
#define BOTTOM_I2C_NUM I2C_NUM_0
|
||||||
#define BOTTOM_I2C_ADDR 126
|
#define BOTTOM_I2C_ADDR 126
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
#include "game_timer.h"
|
#include "game_timer.h"
|
||||||
|
#include <esp_log.h>
|
||||||
|
|
||||||
|
static const char* TAG = "game_timer";
|
||||||
|
|
||||||
static bool is_module_playing;
|
static bool is_module_playing;
|
||||||
static bool is_game_playing;
|
static bool is_game_playing;
|
||||||
@ -12,6 +15,14 @@ static uint32_t module_time_left;
|
|||||||
static void game_timer_task(void *arg);
|
static void game_timer_task(void *arg);
|
||||||
static uint32_t sat_sub(uint32_t x, uint32_t y);
|
static uint32_t sat_sub(uint32_t x, uint32_t y);
|
||||||
|
|
||||||
|
void init_game_timers() {
|
||||||
|
ESP_LOGI(TAG, "Initializing game timers...");
|
||||||
|
|
||||||
|
xTaskCreate(game_timer_task, "game_timers", 4096, NULL, 10, NULL);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Game timers initialized!");
|
||||||
|
}
|
||||||
|
|
||||||
static void write_game_time(uint32_t millis) {
|
static void write_game_time(uint32_t millis) {
|
||||||
if (millis > 60'000) {
|
if (millis > 60'000) {
|
||||||
int disp_time = (millis / 60'000) * 100;
|
int disp_time = (millis / 60'000) * 100;
|
||||||
@ -31,23 +42,19 @@ static void write_module_time(uint32_t millis) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_game_module_timer(void) {
|
void start_game_timer() {
|
||||||
xTaskCreate(game_timer_task, "game_module_timer", 4096, NULL, 10, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void start_game_timer(void) {
|
|
||||||
is_game_playing = true;
|
is_game_playing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_game_timer(void) {
|
void stop_game_timer() {
|
||||||
is_game_playing = false;
|
is_game_playing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_module_timer(void) {
|
void start_module_timer() {
|
||||||
is_module_playing = true;
|
is_module_playing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_module_timer(void) {
|
void stop_module_timer() {
|
||||||
is_module_playing = false;
|
is_module_playing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,8 +98,7 @@ void time_penalty(uint32_t penalty) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void game_timer_task(void *arg)
|
static void game_timer_task(void *arg) {
|
||||||
{
|
|
||||||
TickType_t lastWakeTime = xTaskGetTickCount();
|
TickType_t lastWakeTime = xTaskGetTickCount();
|
||||||
|
|
||||||
const uint32_t frequency = 100;
|
const uint32_t frequency = 100;
|
||||||
@ -118,8 +124,7 @@ static void game_timer_task(void *arg)
|
|||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t sat_sub(uint32_t x, uint32_t y)
|
static uint32_t sat_sub(uint32_t x, uint32_t y) {
|
||||||
{
|
|
||||||
uint32_t res = x - y;
|
uint32_t res = x - y;
|
||||||
res &= -(res <= x);
|
res &= -(res <= x);
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
@ -5,17 +5,17 @@
|
|||||||
#include "sseg.h"
|
#include "sseg.h"
|
||||||
|
|
||||||
/// Initializes the game and module timers.
|
/// Initializes the game and module timers.
|
||||||
void init_game_module_timer(void);
|
void init_game_timers();
|
||||||
|
|
||||||
/// Starts the game timer
|
/// Starts the game timer
|
||||||
void start_game_timer(void);
|
void start_game_timer();
|
||||||
/// Stops the game timer
|
/// Stops the game timer
|
||||||
void stop_game_timer(void);
|
void stop_game_timer();
|
||||||
|
|
||||||
/// Starts the module timer
|
/// Starts the module timer
|
||||||
void start_module_timer(void);
|
void start_module_timer();
|
||||||
/// Stops the module timer
|
/// Stops the module timer
|
||||||
void stop_module_timer(void);
|
void stop_module_timer();
|
||||||
|
|
||||||
/// Sets the game time in ms
|
/// Sets the game time in ms
|
||||||
void set_game_time(int32_t new_time);
|
void set_game_time(int32_t new_time);
|
||||||
|
|||||||
@ -22,8 +22,10 @@ extern sdmmc_card_t *card;
|
|||||||
/// @brief Initializes the SD card
|
/// @brief Initializes the SD card
|
||||||
///
|
///
|
||||||
/// This requires the char_lcd to have been initialized.
|
/// This requires the char_lcd to have been initialized.
|
||||||
/// @return
|
/// @return true if the sd card was successfully initialized
|
||||||
bool init_sd();
|
bool init_sd();
|
||||||
|
|
||||||
|
/// @brief Unmounts the sd card
|
||||||
void deinit_sd();
|
void deinit_sd();
|
||||||
|
|
||||||
#endif /* SD_H */
|
#endif /* SD_H */
|
||||||
@ -57,9 +57,48 @@ esp_err_t play_raw_stop_queue(const char *fp, QueueHandle_t stop_handle) {
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t play_wav(const char *fp) {
|
||||||
|
FILE *fh = fopen(fp, "rb");
|
||||||
|
if (fh == NULL) {
|
||||||
|
ESP_LOGE(TAG, "Failed to open file");
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip the header...
|
||||||
|
fseek(fh, 44, SEEK_SET);
|
||||||
|
|
||||||
|
int16_t *buf = (int16_t*) calloc(AUDIO_BUFFER, sizeof(int16_t));
|
||||||
|
size_t bytes_read = 0;
|
||||||
|
size_t bytes_written = 0;
|
||||||
|
|
||||||
|
bytes_read = fread(buf, sizeof(int16_t), AUDIO_BUFFER, fh);
|
||||||
|
for (int i = 0; i < bytes_read; i++) {
|
||||||
|
buf[i] = buf[i] >> 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2s_channel_preload_data(tx_chan, buf, bytes_read * sizeof(int16_t), &bytes_written);
|
||||||
|
i2s_channel_enable(tx_chan);
|
||||||
|
|
||||||
|
while (bytes_read > 0)
|
||||||
|
{
|
||||||
|
bytes_read = fread(buf, sizeof(int16_t), AUDIO_BUFFER, fh);
|
||||||
|
for (int i = 0; i < bytes_read; i++) {
|
||||||
|
buf[i] = buf[i] >> 2;
|
||||||
|
}
|
||||||
|
// write the buffer to the i2s
|
||||||
|
i2s_channel_write(tx_chan, buf, bytes_read * sizeof(int16_t), &bytes_written, portMAX_DELAY);
|
||||||
|
// ESP_LOGI(TAG, "Bytes read: %d", bytes_read);
|
||||||
|
}
|
||||||
|
|
||||||
|
i2s_channel_disable(tx_chan);
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t play_raw(const char *fp) {
|
esp_err_t play_raw(const char *fp) {
|
||||||
FILE *fh = fopen(fp, "rb");
|
FILE *fh = fopen(fp, "rb");
|
||||||
if (fh == NULL)
|
if (fh == NULL) {
|
||||||
ESP_LOGE(TAG, "Failed to open file");
|
ESP_LOGE(TAG, "Failed to open file");
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
@ -70,18 +109,17 @@ esp_err_t play_raw(const char *fp) {
|
|||||||
size_t bytes_read = 0;
|
size_t bytes_read = 0;
|
||||||
size_t bytes_written = 0;
|
size_t bytes_written = 0;
|
||||||
|
|
||||||
esp_err_t channel_enable_result = i2s_channel_enable(tx_chan);
|
|
||||||
ESP_ERROR_CHECK_WITHOUT_ABORT(channel_enable_result);
|
|
||||||
if (channel_enable_result != ESP_OK) {
|
|
||||||
return channel_enable_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BUFFER, fh);
|
bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BUFFER, fh);
|
||||||
for (int i = 0; i < bytes_read; i++) {
|
for (int i = 0; i < bytes_read; i++) {
|
||||||
write_buf[i] = read_buf[i] << 4;
|
write_buf[i] = read_buf[i] << 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// i2s_channel_enable(tx_handle);
|
i2s_channel_preload_data(tx_chan, write_buf, bytes_read * sizeof(int16_t), &bytes_written);
|
||||||
|
esp_err_t channel_enable_result = i2s_channel_enable(tx_chan);
|
||||||
|
ESP_ERROR_CHECK_WITHOUT_ABORT(channel_enable_result);
|
||||||
|
if (channel_enable_result != ESP_OK) {
|
||||||
|
return channel_enable_result;
|
||||||
|
}
|
||||||
|
|
||||||
while (bytes_read > 0) {
|
while (bytes_read > 0) {
|
||||||
// write the buffer to the i2s
|
// write the buffer to the i2s
|
||||||
@ -90,12 +128,12 @@ esp_err_t play_raw(const char *fp) {
|
|||||||
// int16_t val = buf[i];
|
// int16_t val = buf[i];
|
||||||
// printf("%s0x%04X ", (val < 0 ? "-" : "+"), (val < 0 ? -val : val));
|
// printf("%s0x%04X ", (val < 0 ? "-" : "+"), (val < 0 ? -val : val));
|
||||||
// }>
|
// }>
|
||||||
i2s_channel_write(tx_chan, write_buf, bytes_read * sizeof(int16_t), &bytes_written, portMAX_DELAY);
|
|
||||||
bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BUFFER, fh);
|
bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BUFFER, fh);
|
||||||
for (int i = 0; i < bytes_read; i++) {
|
for (int i = 0; i < bytes_read; i++) {
|
||||||
write_buf[i] = read_buf[i] << 4;
|
write_buf[i] = read_buf[i] << 4;
|
||||||
}
|
}
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
i2s_channel_write(tx_chan, write_buf, bytes_read * sizeof(int16_t), &bytes_written, portMAX_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
i2s_channel_disable(tx_chan);
|
i2s_channel_disable(tx_chan);
|
||||||
@ -130,6 +168,9 @@ void init_speaker(void) {
|
|||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &tx_std_cfg));
|
ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &tx_std_cfg));
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK_WITHOUT_ABORT(play_wav("/sdcard/startup.wav"));
|
||||||
|
ESP_ERROR_CHECK_WITHOUT_ABORT(play_raw("/sdcard/boot.pcm"));
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Speaker initialized!");
|
ESP_LOGI(TAG, "Speaker initialized!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,8 @@ extern i2s_chan_handle_t tx_chan;
|
|||||||
esp_err_t play_raw_stop_queue(const char *fp, QueueHandle_t stop_handle);
|
esp_err_t play_raw_stop_queue(const char *fp, QueueHandle_t stop_handle);
|
||||||
esp_err_t play_raw(const char *fp);
|
esp_err_t play_raw(const char *fp);
|
||||||
|
|
||||||
void init_speaker(void);
|
/// @brief Initalizes the speaker
|
||||||
|
void init_speaker();
|
||||||
void play_example();
|
void play_example();
|
||||||
|
|
||||||
#endif /* SPEAKER_H */
|
#endif /* SPEAKER_H */
|
||||||
@ -1,11 +1,16 @@
|
|||||||
#include "sseg.h"
|
#include "sseg.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
TM1640* sseg = nullptr;
|
TM1640* sseg = nullptr;
|
||||||
|
|
||||||
static const char *TAG = "sseg_driver";
|
static const char *TAG = "sseg";
|
||||||
|
|
||||||
void init_sseg() {
|
void init_sseg() {
|
||||||
|
ESP_LOGI(TAG, "Initializing sseg...");
|
||||||
|
|
||||||
sseg = new TM1640(SSEG_PIN_DATA, SSEG_PIN_CLK, 8);
|
sseg = new TM1640(SSEG_PIN_DATA, SSEG_PIN_CLK, 8);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Sseg initialized!");
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_game_sseg_raw(const uint8_t* digits) {
|
void set_game_sseg_raw(const uint8_t* digits) {
|
||||||
@ -22,7 +27,7 @@ void set_module_sseg_raw(const uint8_t* digits) {
|
|||||||
sseg->setSegments(digits[3], 7);
|
sseg->setSegments(digits[3], 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_game_sseg_num(unsigned int value, int dot_pos) {
|
void set_game_sseg_num(uint32_t value, uint8_t dot_pos) {
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
auto idx = value % 10;
|
auto idx = value % 10;
|
||||||
sseg->sendChar(3-i, TM16XX_NUMBER_FONT[idx], i == dot_pos);
|
sseg->sendChar(3-i, TM16XX_NUMBER_FONT[idx], i == dot_pos);
|
||||||
@ -30,7 +35,7 @@ void set_game_sseg_num(unsigned int value, int dot_pos) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_module_sseg_num(unsigned int value, int dot_pos) {
|
void set_module_sseg_num(uint32_t value, uint8_t dot_pos) {
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
auto idx = value % 10;
|
auto idx = value % 10;
|
||||||
sseg->sendChar(7-i, TM16XX_NUMBER_FONT[idx], i == dot_pos);
|
sseg->sendChar(7-i, TM16XX_NUMBER_FONT[idx], i == dot_pos);
|
||||||
|
|||||||
@ -27,9 +27,9 @@ void set_game_sseg_raw(const uint8_t* digits);
|
|||||||
void set_module_sseg_raw(const uint8_t* digits);
|
void set_module_sseg_raw(const uint8_t* digits);
|
||||||
|
|
||||||
/// sets the game timer to the given number, with the dot at position `dot_pos` from the right (0 => right-most digit).
|
/// sets the game timer to the given number, with the dot at position `dot_pos` from the right (0 => right-most digit).
|
||||||
void set_game_sseg_num(unsigned int value, int dot_pos);
|
void set_game_sseg_num(uint32_t value, uint8_t dot_pos);
|
||||||
|
|
||||||
/// sets the module timer to the given number, with the dot at position `dot_pos` from the right (0 => right-most digit).
|
/// sets the module timer to the given number, with the dot at position `dot_pos` from the right (0 => right-most digit).
|
||||||
void set_module_sseg_num(unsigned int value, int dot_pos);
|
void set_module_sseg_num(uint32_t value, uint8_t dot_pos);
|
||||||
|
|
||||||
#endif /* SSEG_H */
|
#endif /* SSEG_H */
|
||||||
@ -25,8 +25,6 @@ extern "C" void app_main(void) {
|
|||||||
|
|
||||||
init_drivers();
|
init_drivers();
|
||||||
init_tft();
|
init_tft();
|
||||||
init_sseg();
|
|
||||||
init_game_module_timer();
|
|
||||||
init_leds();
|
init_leds();
|
||||||
init_wires();
|
init_wires();
|
||||||
init_power_board();
|
init_power_board();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user