Browse Source

Move everything into one task

main
Hendrik Langer 7 years ago
parent
commit
a711418548
  1. 2
      README.md
  2. 16
      src/datasource.h
  3. 59
      src/main.cpp
  4. 50
      src/ringbuf.cpp
  5. 24
      src/ringbuf.h
  6. 20
      src/sdcard.cpp
  7. 16
      src/sdcard.h
  8. 39
      src/sound.cpp
  9. 20
      src/sound.h

2
README.md

@ -64,6 +64,8 @@ platformio run -t upload && platformio device monitor -b 115200
* internal DAC?
* Add-ons?
* dynamic keypad thresholds
* wav file headers
* stack size in play task
## References

16
src/datasource.h

@ -0,0 +1,16 @@
#ifndef _DATASOURCE_H
#define _DATASOURCE_H
class DataSource {
protected:
public:
static void open(const char *uri);
static size_t read();
static void close();
static bool available();
static unsigned char *buffer;
static unsigned int buf_pos;
private:
};
#endif /* _DATASOURCE_H */

59
src/main.cpp

@ -11,7 +11,6 @@
#include "keyboard.h"
#include "sdcard.h"
#include "sound.h"
#include "ringbuf.h"
#define VERSION "0.0"
@ -21,66 +20,14 @@
Keyboard keyboard;
SDCard sdcard;
Sound sound;
Ringbuf ringbuf = Ringbuf((size_t) BUF_LENGTH);
TaskHandle_t xTaskRead = NULL;
TaskHandle_t xTaskWrite = NULL;
TaskHandle_t xTaskSound = NULL;
bool playing = false;
static const char *soundFile[3][3] = {{"/T0.wav", "/T1.wav", "/T2.wav"},
{"/T3.wav", "/T4.wav", "/T5.wav"},
{"/T6.wav", "/T7.wav", "/T8.wav"}};
void i2s_write_task(void *pvParameter) {
sound.play();
for ( ;; ) {
//TickType_t delay = 10 / portTICK_PERIOD_MS; // max delay: 10ms instead of portMAX_DELAY
uint16_t *start_ptr = ringbuf.getRead();
size_t size_avail = ringbuf.getReadAvail();
int num_samples = 0;
for (int i=0; i<size_avail; i++) {
unsigned int sample = ((unsigned short) start_ptr[i] << 16 & 0xffff0000) | ((unsigned short) start_ptr[i]);
int num_pushed_bytes = i2s_push_sample(sound.i2s_num, (char *)&sample, 0);
num_samples += num_pushed_bytes/4;
}
ringbuf.setRead(num_samples);
// Serial.print(num_samples,DEC);
// Serial.println(" pushed samples to i2s");
if (!ringbuf.active && ringbuf.getReadAvail() == 0) break; // End
vTaskDelay(20 / portTICK_PERIOD_MS);
}
sound.stop();
vTaskDelete( NULL );
}
void sd_read_task(void *pvParameters) {
char *path = (char *) pvParameters;
Serial.println("sdcard: opening File");
sdcard.open(path);
ringbuf.active = true;
xTaskCreate(&i2s_write_task, "write_task", 1024, NULL, 5, &xTaskWrite);
for ( ;; ) {
uint16_t *start_ptr = ringbuf.getWrite();
size_t size_avail = ringbuf.getWriteAvail();
int num_samples = 0;
if (size_avail > 0) {
num_samples = sdcard.read(start_ptr, size_avail);
ringbuf.setWrite(num_samples);
}
Serial.print(num_samples,DEC);
Serial.println(" read samples from sdcard");
if (!sdcard.available()) break; // EOF
vTaskDelay(20 / portTICK_PERIOD_MS); // 20ms
}
ringbuf.active = false;
Serial.println("sdcard: EOF");
sdcard.close();
vTaskDelete( NULL );
}
void setup()
{
// initialize LED digital pin as an output.
@ -98,7 +45,7 @@ void setup()
static const char *bootSound = "/boot.wav";
xTaskCreate(&sd_read_task, "read_task", 2048, (void*)bootSound, 5, &xTaskRead);
xTaskCreate(&(Sound::buffer_refill_task), "buffer_refill_task", 4096, (void*)bootSound, 5, &xTaskSound);
}
void loop()
@ -110,7 +57,7 @@ void loop()
Serial.println("touch");
if (sound.playing == false) {
Serial.println("new task");
xTaskCreate(&sd_read_task, "read_task", 2048, (void*)soundFile[i/3][i%3], 5, &xTaskRead);
xTaskCreate(&(Sound::buffer_refill_task), "buffer_refill_task", 4096, (void*)soundFile[i/3][i%3], 5, &xTaskSound);
}
}
}

50
src/ringbuf.cpp

@ -1,50 +0,0 @@
#include "Arduino.h"
#include "ringbuf.h"
using namespace std;
Ringbuf::Ringbuf(size_t buf_length) {
this->buf = (uint16_t *)malloc(buf_length);
Serial.print("Allocated buffer at: ");
Serial.println((int)this->buf,HEX);
this->buf_length = buf_length;
this->read_pos = 0;
this->write_pos = 0;
this->full = false;
this->active = false;
}
Ringbuf::~Ringbuf() {
free(this->buf);
}
uint16_t *Ringbuf::getWrite() {
return this->buf + write_pos;
}
size_t Ringbuf::getWriteAvail() {
if (full) return 0; // full
else if (read_pos<=write_pos) return buf_length - write_pos; // to the end
else return read_pos - write_pos; // between
}
uint16_t *Ringbuf::getRead() {
return this->buf + read_pos;
}
size_t Ringbuf::getReadAvail() {
if (read_pos==write_pos && !full) return 0; // empty
else if (read_pos>=write_pos) return buf_length - read_pos; // read til end
else return write_pos - read_pos;
}
void Ringbuf::setWrite(size_t bytes){
write_pos = (write_pos+bytes)%buf_length;
if(read_pos==write_pos) full = true;
}
void Ringbuf::setRead(size_t bytes){
read_pos = (read_pos+bytes)%buf_length;
if(read_pos==write_pos) full = false;
}

24
src/ringbuf.h

@ -1,24 +0,0 @@
#ifndef _RINGBUF_H
#define _RINGBUF_H
class Ringbuf {
public:
Ringbuf(size_t buf_length);
~Ringbuf();
uint16_t *buf;
unsigned int buf_length;
unsigned int read_pos;
unsigned int write_pos;
uint16_t *getWrite();
size_t getWriteAvail();
uint16_t *getRead();
size_t getReadAvail();
void setWrite(size_t bytes);
void setRead(size_t bytes);
bool full;
bool active = false;
private:
};
#endif /* _RINGBUF_H */

20
src/sdcard.cpp

@ -13,11 +13,16 @@
#include "hardware.h"
#include "sdcard.h"
#include "sound.h"
#include "datasource.h"
using namespace std;
static const char* TAG = "SDCard";
unsigned char *DataSource::buffer = NULL;
unsigned int DataSource::buf_pos = 0;
File SDCard::file;
SDCard::SDCard() {
}
@ -57,21 +62,24 @@ void SDCard::umount() {
}
void SDCard::open(const char *path) {
file = fs.open(path);
if(!file){
DataSource::buffer = (unsigned char *)malloc(BUF_LENGTH);
Serial.print("Allocated buffer at: "); Serial.println((int)(DataSource::buffer),HEX);
SDCard::file = (SDCard::fs).open(path);
if(!SDCard::file){
Serial.println("Failed to open file for reading");
return;
}
}
void SDCard::close() {
file.close();
free(DataSource::buffer);
SDCard::file.close();
}
bool SDCard::available() {
return file.available();
return SDCard::file.available();
}
size_t SDCard::read(uint16_t *buffer, size_t len){
return file.read((uint8_t *)buffer, len*sizeof(uint16_t))/sizeof(uint16_t);
size_t SDCard::read(){
return SDCard::file.read((uint8_t *)DataSource::buffer, BUF_LENGTH);
}

16
src/sdcard.h

@ -5,21 +5,23 @@
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include "datasource.h"
class SDCard {
class SDCard: public DataSource {
public:
SDCard();
void mount();
void umount();
void open(const char *path);
void close();
size_t read(uint16_t *buffer, size_t len);
bool available();
static void open(const char *path);
static void close();
static size_t read();
static bool available();
static File file;
static constexpr fs::FS &fs = SD;
private:
fs::FS &fs = SD;
uint8_t cardType;
uint64_t cardSize;
File file;
};
#endif /* _SDCARD_H */

39
src/sound.cpp

@ -7,6 +7,8 @@
*/
#include "sound.h"
#include "datasource.h"
#include "sdcard.h"
#include "Arduino.h"
#include <stdio.h>
@ -26,6 +28,8 @@
using namespace std;
bool Sound::playing = false;
Sound::Sound() {
}
@ -88,6 +92,41 @@ void Sound::end() {
i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver
}
void Sound::buffer_refill_task(void *pvParameter) {
char *path = (char *) pvParameter;
Serial.println("sdcard: opening File");
SDCard::open(path);
Sound::play();
while (SDCard::available()) {
// get chunk of data
SDCard::read(); // overwrite buffer
DataSource::buf_pos = 0;
while (DataSource::buf_pos < BUF_LENGTH) {
uint16_t *buf = (uint16_t *) DataSource::buffer;
int buf_pos = (DataSource::buf_pos)/4;
// convert data
//unsigned int sample = ((unsigned short) DataSource::buffer[DataSource::buf_pos] << 16 & 0xffff0000) | ((unsigned short) DataSource::buffer[DataSource::buf_pos]);
unsigned int sample = ((unsigned short) buf[buf_pos] << 16 & 0xffff0000) | ((unsigned short) DataSource::buffer[buf_pos]);
// push samples
int num_pushed_bytes = i2s_push_sample(Sound::i2s_num, (char *)&sample, 0);
if (num_pushed_bytes == 0) {
Serial.println("i2s buf filled");
vTaskDelay(20 / portTICK_PERIOD_MS);
}
DataSource::buf_pos += num_pushed_bytes;
}
// Buffer now empty
//TickType_t delay = 10 / portTICK_PERIOD_MS; // max delay: 10ms instead of portMAX_DELAY
vTaskDelay(20 / portTICK_PERIOD_MS);
}
Serial.println("sdcard: EOF");
SDCard::close();
Sound::stop();
vTaskDelete( NULL );
}
/* callback(?) for new audio data */
int Sound::render_sample_block(uint16_t *sample_buf_left, uint16_t *sample_buf_right, int num_samples) {
TickType_t delay = 10 / portTICK_PERIOD_MS; // max delay: 10ms instead of portMAX_DELAY

20
src/sound.h

@ -7,29 +7,21 @@
#include "hardware.h"
typedef struct {
int16_t buf[512];
int len;
int index;
int playing;
} i2sbuffer_t;
class Sound {
public:
Sound();
void init();
void end();
void loop();
// void close();
void play();
static void play();
// void pause();
void stop();
static void stop();
int render_sample_block(uint16_t *sample_buf_left, uint16_t *sample_buf_right, int num_samples);
const i2s_port_t i2s_num = (i2s_port_t)I2S_NUM;
bool playing;
static const i2s_port_t i2s_num = (i2s_port_t)I2S_NUM;
static bool playing;
static void buffer_refill_task(void *pvParameter);
private:
i2sbuffer_t buffer;
TaskHandle_t xTaskRefillBuffer;
};
#endif /* _SOUND_H */

Loading…
Cancel
Save