Teensy 3.2 winbond flash based drum sampler - enough speed?

Status
Not open for further replies.

alex1982

Member
Hi All,

I would like to embark on a teensy 3.x based ultra lo-fi 8bit sampling drum machine.

Ideally it would be able to read 8 tracks at once, with the ability to overwrite one in real time, from analog input

Considering the ultra lo-fi nature (but nice for nasty little drum sounds), can an SPI winbond flash chip (W25Q32) read 8 bytes and write 1 byte within a 22,000hz interrupt?

I understand that erasing/overwriting files using the Serial Flash library's file structure can cause some delays,
Can the chip be randomly accessed for single byte reads/writes like an eeprom, bypassing the file structure?

I'm well aware of the audio library which is awesome, but seduced by the idea of doing this manually (and learning along the way) as we are dealing with byte long samples

Thanks in advance for any guidance.
Alex
 
If your goal is learning, this is a great idea.

If your goal is a great audio system, the audio library at 44 kHz 16 bit will vastly outperform any attempt to do 22 kHz 8 bit using one interrupt per sample. The audio library uses DMA transfers, which results a much lower interrupt rate because each interrupt set up a DMA transfer that automatically moves a block of audio data. You might think half the sample rate and half the data size is 4X faster, but processing 1 sample at a time has massive overhead, both interrupt entry/exit, and software overhead. The DMA and block-based approach is *much* more than 4X as efficient!

The SPI flash chip can probably handle this speed. Writing 256 bytes is the most efficient, so queue up 256 bytes before write. The overhead for writing a single byte will probably be too slow.

SerialFlash does support suspending writes, but there's a small performance penalty. You really should try to use buffers for many samples when reading. If you do interrupt the write, read many samples into RAM, so you (probably) will not need to interrupt it again before the write completes.
 
Many thanks for the insightful feedback, Paul!
Sounds like the byte by byte approach would have taught how not to do it :)
I'll play with the audio library instead!
Many thanks
Alex
 
Hi Paul,

I am using the "copy from SD card program" of Serial Flash but when connection SD card and Serial Flash together only SD card works.

Also, When initializing Serial first, it works and program hangs when reaches copying section of code.

Below is the code.(only copying one file).

#include <SerialFlash.h>
#include <SD.h>
#include <SPI.h>

/*const int SDchipSelect = 4; // Audio Shield has SD card CS on pin 10
const int FlashChipSelect = 6;*/

SerialFlashFile ff;
File f;
int n1=0;
void setup() {
//uncomment these if using Teensy audio shield
//SPI.setSCK(14); // Audio shield has SCK on pin 14
//SPI.setMOSI(7); // Audio shield has MOSI on pin 7

// wait up to 10 seconds for Arduino Serial Monitor
unsigned long startMillis = millis();
while (!Serial && (millis() - startMillis < 10000)) ;
delay(100);
Serial.println("Copy all files from SD Card to SPI Flash");

SPI.setMOSI(11);
SPI.setMISO(12);
SPI.setSCK(13);
if (!SerialFlash.begin()) {
error("Unable to access SPI Flash chip");
}
SerialFlash.eraseAll();
if (SerialFlash.createErasable("PLAY1.WAV", 111111)) {
Serial.println("Create success");
ff = SerialFlash.open("PLAY1.WAV");
if (ff)
Serial.println("open success");
else
Serial.println("open UNsuccess");
}
else
Serial.println("Create UNsuccess");

SPI.setMOSI(7);
SPI.setMISO(8);
SPI.setSCK(14);
if (!SD.begin(9)) {
error("Unable to access SD card");
}
// SPI.setMOSI(11);
// SPI.setMISO(12);
// SPI.setSCK(13);
// if (!SerialFlash.begin()) {
// error("Unable to access SPI Flash chip");
// }

int count = 0;
File rootdir = SD.open("/");
while (1) {
// open a file from the SD card
Serial.println();
f = rootdir.openNextFile();
if (!f) break;
const char *filename = f.name();
Serial.print(filename);
Serial.print(" ");
unsigned long length = f.size();
Serial.println(length);
// SerialFlash.begin();
//SerialFlash.eraseAll();
// check if this file is already on the Flash chip
/*if (SerialFlash.exists(filename)) {
Serial.println(" already exists on the Flash chip");
SerialFlashFile ff = SerialFlash.open(filename);
if (ff && ff.size() == f.size()) {
Serial.println(" size is the same, comparing data...");
if (compareFiles(f, ff) == true) {
Serial.println(" files are identical :)");
f.close();
ff.close();
continue; // advance to next file
} else {
Serial.println(" files are different");
}
} else {
Serial.print(" size is different, ");
Serial.print(ff.size());
Serial.println(" bytes");
}
// delete the copy on the Flash chip, if different
Serial.println(" delete file from Flash chip");
SerialFlash.remove(filename);
}*/

// create the file on the Flash chip and copy data

// SerialFlash.begin();
n1++;
if(n1==1)
{
Serial.print(" copying");
// copy data loop
unsigned long count = 0;
unsigned char dotcount = 9;
while (count < length) {
char buf[256];
unsigned int n;
n = f.read(buf, 256);
ff.write(buf, n);
count = count + n;
Serial.print(".");
if (++dotcount > 100) {
Serial.println();
dotcount = 0;
}
}
ff.close();
if (dotcount > 0) Serial.println();
} else {
Serial.println(" error opening freshly created file!");
Serial.println(n1);
}
// } else {
// Serial.println(" unable to create file");
// }
f.close();
}
rootdir.close();
delay(10);
Serial.println("Finished All Files");
}


bool compareFiles(File &file, SerialFlashFile &ffile) {
file.seek(0);
ffile.seek(0);
unsigned long count = file.size();
while (count > 0) {
char buf1[128], buf2[128];
unsigned long n = count;
if (n > 128) n = 128;
file.read(buf1, n);
ffile.read(buf2, n);
if (memcmp(buf1, buf2, n) != 0) return false; // differ
count = count - n;
}
return true; // all data identical
}


void loop() {
}

void error(const char *message) {
while (1) {
Serial.println(message);
delay(2500);
}
}
 
These libraries can't use SPI this way:

SPI.setMOSI(11);
SPI.setMISO(12);
SPI.setSCK(13);
if (!SerialFlash.begin()) {

// ......

SPI.setMOSI(7);
SPI.setMISO(8);
SPI.setSCK(14);
if (!SD.begin(9)) {

You really do need to use the same pins for MOSI, MISO and SCK.
 
means paul I have to use same MISO, MOSI and SCK and different chip select.
Processor will take care of data flowing.
 
Status
Not open for further replies.
Back
Top