Created
April 5, 2021 11:44
-
-
Save newdigate/109280f4f67463b5226b3c9afb4f0882 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Audio.h> | |
#include <ST7735_t3.h> // Hardware-specific library | |
#include <ResponsiveAnalogRead.h> | |
#include "teensy_eurorack.h" | |
#include "output_spi.h" | |
#include "ScopeView.h" | |
ST7735_t3 TFT = ST7735_t3(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST); | |
// GUItool: begin automatically generated code | |
AudioInputTDM tdm; //xy=210.11108779907227,555.4443893432617 | |
AudioOutputSPI ad7606; //xy=253.8888282775879,242.22220611572266 | |
AudioRecordQueue audioRecordQueue9; //xy=551.6665954589844,622.2221488952637 | |
AudioRecordQueue audioRecordQueue7; //xy=553.8888320922852,354.444393157959 | |
AudioRecordQueue audioRecordQueue10; //xy=553.888916015625,655.5554962158203 | |
AudioRecordQueue audioRecordQueue11; //xy=553.8889541625977,688.8888387680054 | |
AudioRecordQueue audioRecordQueue8; //xy=556.1110382080078,391.11108016967773 | |
AudioRecordQueue audioRecordQueue12; //xy=555.0000762939453,722.2222347259521 | |
AudioRecordQueue audioRecordQueue13; //xy=554.9999313354492,756.6666603088379 | |
AudioRecordQueue audioRecordQueue14; //xy=554.9999313354492,792.2221641540527 | |
AudioRecordQueue audioRecordQueue6; //xy=557.2220993041992,308.8888530731201 | |
AudioRecordQueue audioRecordQueue5; //xy=564.9999771118164,256.66662406921387 | |
AudioRecordQueue audioRecordQueue3; //xy=567.2221984863281,176.6666259765625 | |
AudioRecordQueue audioRecordQueue4; //xy=569.4443359375,217.77774238586426 | |
AudioRecordQueue audioRecordQueue1; //xy=570.5554885864258,97.77776336669922 | |
AudioRecordQueue audioRecordQueue2; //xy=572.7776794433594,134.4444284439087 | |
AudioSynthWaveformSine sine10; //xy=751.1111102634006,491.11109627617725 | |
AudioSynthWaveformSine sine13; //xy=753.3333324856228,603.3333184983995 | |
AudioSynthWaveformSine sine15; //xy=753.3333625793457,683.3333053588867 | |
AudioSynthWaveformSine sine16; //xy=753.3333587646484,722.2221755981445 | |
AudioSynthWaveformSine sine12; //xy=754.4444435967339,559.9999851650662 | |
AudioSynthWaveformSine sine9; //xy=757.7777769300673,453.33331849839954 | |
AudioSynthWaveformSine sine14; //xy=757.7777862548828,644.4443759918213 | |
AudioSynthWaveformSine sine11; //xy=758.8888880411783,525.5555407206217 | |
AudioSynthWaveformSine sine1; //xy=766.9999732971191,97.77776336669922 | |
AudioSynthWaveformSine sine2; //xy=766.999927520752,133.3333683013916 | |
AudioSynthWaveformSine sine8; //xy=769.2221870422363,356.66664123535156 | |
AudioSynthWaveformSine sine3; //xy=770.3332901000977,172.22220039367676 | |
AudioSynthWaveformSine sine5; //xy=770.3332672119141,248.88892650604248 | |
AudioSynthWaveformSine sine6; //xy=770.3332710266113,284.4444122314453 | |
AudioSynthWaveformSine sine7; //xy=770.3332138061523,318.8888273239136 | |
AudioSynthWaveformSine sine4; //xy=772.5555877685547,210.00000286102295 | |
AudioSynthWaveformDc dc1; //xy=226,901 | |
AudioSynthWaveformDc dc2; //xy=226,946 | |
AudioSynthWaveformDc dc3; //xy=227,995 | |
AudioSynthWaveformDc dc4; //xy=229,1039 | |
AudioRecordQueue queue4; //xy=534,1040 | |
AudioRecordQueue queue1; //xy=550,902 | |
AudioRecordQueue queue2; //xy=551,945 | |
AudioRecordQueue queue3; //xy=560,989 | |
AudioOutputTDM tdm2; //xy=1037.8889694213867,542.1110763549805 | |
AudioConnection patchCord1(tdm, 0, audioRecordQueue9, 0); | |
AudioConnection patchCord2(tdm, 2, audioRecordQueue10, 0); | |
AudioConnection patchCord3(tdm, 4, audioRecordQueue11, 0); | |
AudioConnection patchCord4(tdm, 6, audioRecordQueue12, 0); | |
AudioConnection patchCord5(tdm, 8, audioRecordQueue13, 0); | |
AudioConnection patchCord6(tdm, 10, audioRecordQueue14, 0); | |
AudioConnection patchCord7(ad7606, 0, audioRecordQueue1, 0); | |
AudioConnection patchCord8(ad7606, 1, audioRecordQueue2, 0); | |
AudioConnection patchCord9(ad7606, 2, audioRecordQueue3, 0); | |
AudioConnection patchCord10(ad7606, 3, audioRecordQueue4, 0); | |
AudioConnection patchCord11(ad7606, 4, audioRecordQueue5, 0); | |
AudioConnection patchCord12(ad7606, 5, audioRecordQueue6, 0); | |
AudioConnection patchCord13(ad7606, 6, audioRecordQueue7, 0); | |
AudioConnection patchCord14(ad7606, 7, audioRecordQueue8, 0); | |
AudioConnection patchCord15(sine10, 0, tdm2, 2); | |
AudioConnection patchCord16(sine13, 0, tdm2, 8); | |
AudioConnection patchCord17(sine15, 0, tdm2, 12); | |
AudioConnection patchCord18(sine16, 0, tdm2, 14); | |
AudioConnection patchCord19(sine12, 0, tdm2, 6); | |
AudioConnection patchCord20(sine9, 0, tdm2, 0); | |
AudioConnection patchCord21(sine14, 0, tdm2, 10); | |
AudioConnection patchCord22(sine11, 0, tdm2, 4); | |
AudioConnection patchCord23(sine1, 0, ad7606, 0); | |
AudioConnection patchCord24(sine2, 0, ad7606, 1); | |
AudioConnection patchCord25(sine8, 0, ad7606, 7); | |
AudioConnection patchCord26(sine3, 0, ad7606, 2); | |
AudioConnection patchCord27(sine5, 0, ad7606, 4); | |
AudioConnection patchCord28(sine6, 0, ad7606, 5); | |
AudioConnection patchCord29(sine7, 0, ad7606, 6); | |
AudioConnection patchCord30(sine4, 0, ad7606, 3); | |
AudioConnection patchCord31(dc1, queue1); | |
AudioConnection patchCord32(dc2, queue2); | |
AudioConnection patchCord33(dc3, queue3); | |
AudioConnection patchCord34(dc4, queue4); | |
AudioControlCS42448 cs42448_1; //xy=553.4443435668945,831.111083984375 | |
// GUItool: end automatically generated code | |
uint16_t colors[8] = {ST7735_GREEN,ST7735_RED,ST7735_BLUE,ST7735_CYAN,ST7735_MAGENTA,ST7735_YELLOW,0xFFAA,ST7735_WHITE}; | |
ScopeView scopeViewCV1 = ScopeView(TFT, audioRecordQueue1, colors[0], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewCV2 = ScopeView(TFT, audioRecordQueue2, colors[1], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewCV3 = ScopeView(TFT, audioRecordQueue3, colors[2], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewCV4 = ScopeView(TFT, audioRecordQueue4, colors[3], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewCV5 = ScopeView(TFT, audioRecordQueue5, colors[4], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewCV6 = ScopeView(TFT, audioRecordQueue6, colors[5], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewCV7 = ScopeView(TFT, audioRecordQueue7, colors[6], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewCV8 = ScopeView(TFT, audioRecordQueue8, colors[7], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewAudio1 = ScopeView(TFT, audioRecordQueue9, colors[0], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewAudio2 = ScopeView(TFT, audioRecordQueue10, colors[1], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewAudio3 = ScopeView(TFT, audioRecordQueue11, colors[2], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewAudio4 = ScopeView(TFT, audioRecordQueue12, colors[3], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewAudio5 = ScopeView(TFT, audioRecordQueue13, colors[4], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewAudio6 = ScopeView(TFT, audioRecordQueue14, colors[5], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewPot1 = ScopeView(TFT, queue1, colors[2], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewPot2 = ScopeView(TFT, queue2, colors[3], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewPot3 = ScopeView(TFT, queue3, colors[4], (int16_t)ST7735_BLACK, 64); | |
ScopeView scopeViewPot4 = ScopeView(TFT, queue4, colors[5], (int16_t)ST7735_BLACK, 64); | |
ResponsiveAnalogRead analogPot1(TEENSY_EURORACK_PIN_POT1, true, 1.0); | |
ResponsiveAnalogRead analogPot2(TEENSY_EURORACK_PIN_POT2, true, 1.0); | |
ResponsiveAnalogRead analogPot3(TEENSY_EURORACK_PIN_POT3, true, 1.0); | |
ResponsiveAnalogRead analogPot4(TEENSY_EURORACK_PIN_POT4, true, 1.0); | |
unsigned long start_time; | |
void setup() { | |
pinMode(TEENSY_EURORACK_PIN_POT1, INPUT_DISABLE); | |
pinMode(TEENSY_EURORACK_PIN_POT2, INPUT_DISABLE); | |
pinMode(TEENSY_EURORACK_PIN_POT3, INPUT_DISABLE); | |
pinMode(TEENSY_EURORACK_PIN_POT4, INPUT_DISABLE); | |
analogReadResolution(12); | |
analogPot1.enableEdgeSnap(); | |
analogPot1.setAnalogResolution(4096); | |
analogPot2.enableEdgeSnap(); | |
analogPot2.setAnalogResolution(4096); | |
analogPot3.enableEdgeSnap(); | |
analogPot3.setAnalogResolution(4096); | |
analogPot4.enableEdgeSnap(); | |
analogPot4.setAnalogResolution(4096); | |
Serial.begin(9600); | |
//while(!Serial) { | |
// delay(1); | |
//} | |
AudioNoInterrupts(); | |
AudioMemory(160); | |
cs42448_1.enable(); | |
cs42448_1.volume(1); | |
AudioInterrupts(); // enable, both tones will start together | |
TFT.initR(INITR_144GREENTAB); | |
TFT.setRotation(3); | |
TFT.fillScreen(ST7735_BLACK); | |
TFT.useFrameBuffer(true); | |
TFT.updateScreenAsync(true); | |
//noInterrupts(); | |
sine8.frequency(1000); | |
sine8.amplitude(0.7); | |
sine7.frequency(AUDIO_SAMPLE_RATE_EXACT/128.0); | |
sine7.amplitude(0.7); | |
sine6.frequency(AUDIO_SAMPLE_RATE_EXACT*2.0/128.0); | |
sine6.amplitude(0.7); | |
sine5.frequency(AUDIO_SAMPLE_RATE_EXACT*0.5/128.0); | |
sine5.amplitude(0.7); | |
sine4.frequency(AUDIO_SAMPLE_RATE_EXACT*4.0/128.0); | |
sine4.amplitude(0.7); | |
sine3.frequency(AUDIO_SAMPLE_RATE_EXACT*8.0/128.0); | |
sine3.amplitude(0.7); | |
sine2.frequency(AUDIO_SAMPLE_RATE_EXACT*0.25/128.0); | |
sine2.amplitude(0.7); | |
sine1.frequency(AUDIO_SAMPLE_RATE_EXACT*0.125/128.0); | |
sine1.amplitude(0.7); | |
sine9.frequency(AUDIO_SAMPLE_RATE_EXACT*12.0/128.0); | |
sine9.amplitude(0.7); | |
sine10.frequency(AUDIO_SAMPLE_RATE_EXACT*6.0/128.0); | |
sine10.amplitude(0.7); | |
sine11.frequency(250); | |
sine11.amplitude(0.7); | |
sine12.frequency(100); | |
sine12.amplitude(0.7); | |
sine13.frequency(125); | |
sine13.amplitude(0.7); | |
sine14.frequency(750); | |
sine14.amplitude(0.7); | |
sine15.frequency(4000); | |
sine15.amplitude(0.7); | |
sine16.frequency(1500); | |
sine16.amplitude(0.7); | |
audioRecordQueue1.begin(); | |
audioRecordQueue2.begin(); | |
audioRecordQueue3.begin(); | |
audioRecordQueue4.begin(); | |
audioRecordQueue5.begin(); | |
audioRecordQueue6.begin(); | |
audioRecordQueue7.begin(); | |
audioRecordQueue8.begin(); | |
audioRecordQueue9.begin(); | |
audioRecordQueue10.begin(); | |
audioRecordQueue11.begin(); | |
audioRecordQueue12.begin(); | |
audioRecordQueue13.begin(); | |
audioRecordQueue14.begin(); | |
queue1.begin(); | |
queue2.begin(); | |
queue3.begin(); | |
queue4.begin(); | |
dc1.amplitude(0.5, 1); | |
dc1.amplitude(-0.5, 1); | |
dc1.amplitude(0.25, 1); | |
dc1.amplitude(-0.25, 1); | |
//interrupts(); | |
start_time = millis(); | |
} | |
char timestring[] = " "; | |
void updateTFTTime(char *oldString, char *newString, bool rerender) { | |
int c=0; | |
if (!rerender) { | |
int len1 = strlen(oldString); | |
int len2 = strlen(newString); | |
while(oldString[c] == newString[c] && c < len1 && c < len2 ){ | |
c++; | |
} | |
} | |
TFT.setCursor(c * 6,0); | |
TFT.setTextColor(ST7735_BLACK); | |
TFT.print( (char * ) (oldString + c)); | |
TFT.setCursor(c * 6,0); | |
TFT.setTextColor(ST7735_WHITE); | |
TFT.print( (char * ) (newString + c)); | |
} | |
unsigned count = 0, count2 = 0; | |
void loop() { | |
if (count % 20 == 0) { | |
scopeViewCV1.checkForUpdateBuffer(); | |
scopeViewCV2.checkForUpdateBuffer(); | |
scopeViewCV3.checkForUpdateBuffer(); | |
scopeViewCV4.checkForUpdateBuffer(); | |
scopeViewCV5.checkForUpdateBuffer(); | |
scopeViewCV6.checkForUpdateBuffer(); | |
scopeViewCV7.checkForUpdateBuffer(); | |
scopeViewCV8.checkForUpdateBuffer(); | |
scopeViewAudio1.checkForUpdateBuffer(); | |
scopeViewAudio2.checkForUpdateBuffer(); | |
scopeViewAudio3.checkForUpdateBuffer(); | |
scopeViewAudio4.checkForUpdateBuffer(); | |
scopeViewAudio5.checkForUpdateBuffer(); | |
scopeViewAudio6.checkForUpdateBuffer(); | |
scopeViewPot1.checkForUpdateBuffer(); | |
scopeViewPot2.checkForUpdateBuffer(); | |
scopeViewPot3.checkForUpdateBuffer(); | |
scopeViewPot4.checkForUpdateBuffer(); | |
scopeViewCV1.undrawScope(); | |
scopeViewCV2.undrawScope(); | |
scopeViewCV3.undrawScope(); | |
scopeViewCV4.undrawScope(); | |
scopeViewCV5.undrawScope(); | |
scopeViewCV6.undrawScope(); | |
scopeViewCV7.undrawScope(); | |
scopeViewCV8.undrawScope(); | |
scopeViewAudio1.undrawScope(); | |
scopeViewAudio2.undrawScope(); | |
scopeViewAudio3.undrawScope(); | |
scopeViewAudio4.undrawScope(); | |
scopeViewAudio5.undrawScope(); | |
scopeViewAudio6.undrawScope(); | |
scopeViewPot1.undrawScope(); | |
scopeViewPot2.undrawScope(); | |
scopeViewPot3.undrawScope(); | |
scopeViewPot4.undrawScope(); | |
scopeViewCV1.drawScope(); | |
scopeViewCV2.drawScope(); | |
scopeViewCV3.drawScope(); | |
scopeViewCV4.drawScope(); | |
scopeViewCV5.drawScope(); | |
scopeViewCV6.drawScope(); | |
scopeViewCV7.drawScope(); | |
scopeViewCV8.drawScope(); | |
scopeViewAudio1.drawScope(); | |
scopeViewAudio2.drawScope(); | |
scopeViewAudio3.drawScope(); | |
scopeViewAudio4.drawScope(); | |
scopeViewAudio5.drawScope(); | |
scopeViewAudio6.drawScope(); | |
scopeViewPot1.drawScope(); | |
scopeViewPot2.drawScope(); | |
scopeViewPot3.drawScope(); | |
scopeViewPot4.drawScope(); | |
//TFT.updateScreen(); | |
} | |
if (audioRecordQueue1.available() > 2) { | |
audioRecordQueue1.end(); | |
while (audioRecordQueue1.available() > 2) { | |
audioRecordQueue1.readBuffer(); | |
audioRecordQueue1.freeBuffer(); | |
} | |
audioRecordQueue1.begin(); | |
} | |
if (audioRecordQueue2.available() > 2) { | |
audioRecordQueue2.end(); | |
while (audioRecordQueue2.available() > 2) { | |
audioRecordQueue2.readBuffer(); | |
audioRecordQueue2.freeBuffer(); | |
} | |
audioRecordQueue2.begin(); | |
} | |
if (audioRecordQueue3.available() > 2) { | |
audioRecordQueue3.end(); | |
while (audioRecordQueue3.available() > 2) { | |
audioRecordQueue3.readBuffer(); | |
audioRecordQueue3.freeBuffer(); | |
} | |
audioRecordQueue3.begin(); | |
} | |
if (audioRecordQueue4.available() > 2) { | |
audioRecordQueue4.end(); | |
while (audioRecordQueue4.available() > 2) { | |
audioRecordQueue4.readBuffer(); | |
audioRecordQueue4.freeBuffer(); | |
} | |
audioRecordQueue4.begin(); | |
} | |
if (audioRecordQueue5.available() > 2) { | |
audioRecordQueue5.end(); | |
while (audioRecordQueue5.available() > 2) { | |
audioRecordQueue5.readBuffer(); | |
audioRecordQueue5.freeBuffer(); | |
} | |
audioRecordQueue5.begin(); | |
} | |
if (audioRecordQueue6.available() > 2) { | |
audioRecordQueue6.end(); | |
while (audioRecordQueue6.available() > 2) { | |
audioRecordQueue6.readBuffer(); | |
audioRecordQueue6.freeBuffer(); | |
} | |
audioRecordQueue6.begin(); | |
} | |
if (audioRecordQueue7.available() > 2) { | |
audioRecordQueue7.end(); | |
while (audioRecordQueue7.available() > 2) { | |
audioRecordQueue7.readBuffer(); | |
audioRecordQueue7.freeBuffer(); | |
} | |
audioRecordQueue7.begin(); | |
} | |
if (audioRecordQueue8.available() > 2) { | |
audioRecordQueue8.end(); | |
while (audioRecordQueue8.available() > 2) { | |
audioRecordQueue8.readBuffer(); | |
audioRecordQueue8.freeBuffer(); | |
} | |
audioRecordQueue8.begin(); | |
} | |
if (audioRecordQueue9.available() > 2) { | |
audioRecordQueue9.end(); | |
while (audioRecordQueue9.available() > 2) { | |
audioRecordQueue9.readBuffer(); | |
audioRecordQueue9.freeBuffer(); | |
} | |
audioRecordQueue9.begin(); | |
} | |
if (audioRecordQueue10.available() > 2) { | |
audioRecordQueue10.end(); | |
while (audioRecordQueue10.available() > 2) { | |
audioRecordQueue10.readBuffer(); | |
audioRecordQueue10.freeBuffer(); | |
} | |
audioRecordQueue10.begin(); | |
} | |
if (audioRecordQueue11.available() > 2) { | |
audioRecordQueue11.end(); | |
while (audioRecordQueue11.available() > 2) { | |
audioRecordQueue11.readBuffer(); | |
audioRecordQueue11.freeBuffer(); | |
} | |
audioRecordQueue11.begin(); | |
} | |
if (audioRecordQueue12.available() > 2) { | |
audioRecordQueue12.end(); | |
while (audioRecordQueue12.available() > 2) { | |
audioRecordQueue12.readBuffer(); | |
audioRecordQueue12.freeBuffer(); | |
} | |
audioRecordQueue12.begin(); | |
} | |
if (audioRecordQueue13.available() > 2) { | |
audioRecordQueue13.end(); | |
while (audioRecordQueue13.available() > 2) { | |
audioRecordQueue13.readBuffer(); | |
audioRecordQueue13.freeBuffer(); | |
} | |
audioRecordQueue13.begin(); | |
} | |
if (audioRecordQueue14.available() > 2) { | |
audioRecordQueue14.end(); | |
while (audioRecordQueue14.available() > 2) { | |
audioRecordQueue14.readBuffer(); | |
audioRecordQueue14.freeBuffer(); | |
} | |
audioRecordQueue14.begin(); | |
} | |
if (queue1.available() > 2) { | |
queue1.end(); | |
while (queue1.available() > 2) { | |
queue1.readBuffer(); | |
queue1.freeBuffer(); | |
} | |
queue1.begin(); | |
} | |
if (queue2.available() > 2) { | |
queue2.end(); | |
while (queue2.available() > 2) { | |
queue2.readBuffer(); | |
queue2.freeBuffer(); | |
} | |
queue2.begin(); | |
} | |
if (queue3.available() > 2) { | |
queue3.end(); | |
while (queue3.available() > 2) { | |
queue3.readBuffer(); | |
queue3.freeBuffer(); | |
} | |
queue3.begin(); | |
} | |
if (queue4.available() > 2) { | |
queue4.end(); | |
while (queue4.available() > 2) { | |
queue4.readBuffer(); | |
queue4.freeBuffer(); | |
} | |
queue4.begin(); | |
} | |
if (count % 20000 == 0) { | |
analogPot1.update(); | |
analogPot2.update(); | |
analogPot3.update(); | |
analogPot4.update(); | |
// if the responsive value has change, print out 'changed' | |
if(analogPot1.hasChanged()) { | |
float ff = (analogPot1.getValue()/2048.0) - 1.0f; | |
dc1.amplitude(ff, 10); | |
} | |
if(analogPot2.hasChanged()) { | |
float ff = (analogPot2.getValue()/2048.0) - 1.0f; | |
dc2.amplitude(ff, 10); | |
} | |
if(analogPot3.hasChanged()) { | |
float ff = (analogPot3.getValue()/2048.0) - 1.0f; | |
dc3.amplitude(ff, 10); | |
} | |
if(analogPot4.hasChanged()) { | |
float ff = (analogPot4.getValue()/2048.0) - 1.0f; | |
dc4.amplitude(ff, 10); | |
} | |
} | |
//delayMicroseconds(100); | |
count++; | |
if (count % 10000 == 0) { | |
unsigned long newmillis = millis() - start_time; | |
count2++; | |
unsigned long days = newmillis / (1000 * 60 * 60 * 24); | |
unsigned long remainer = newmillis - (days * 1000 * 60 * 60 * 24); | |
unsigned long hours = remainer / (1000 * 60 * 60); | |
remainer = remainer - (hours * 1000 * 60 * 60); | |
unsigned long minutes = remainer / (1000 * 60); | |
remainer = remainer - (minutes * 1000 * 60); | |
unsigned long seconds = remainer / 1000; | |
remainer = remainer - (seconds * 1000); | |
//tft.fillScreen(ST7735_BLACK); | |
char newtimestring[] = " "; | |
int n = sprintf(newtimestring, "%2u:%2u:%2u:%2u.%u", days, hours, minutes, seconds, remainer / 100); | |
bool fullUpdate = count2 % 100 == 0; | |
if (fullUpdate) { | |
Serial.print(timestring); | |
Serial.print(" "); | |
Serial.print(count2/100); | |
Serial.print(" all="); | |
Serial.print(AudioProcessorUsage()); | |
Serial.print(","); | |
Serial.print(AudioProcessorUsageMax()); | |
Serial.print(" "); | |
Serial.print("Memory: "); | |
Serial.print(AudioMemoryUsage()); | |
Serial.print(","); | |
Serial.print(AudioMemoryUsageMax()); | |
Serial.print(" "); | |
Serial.print("Free Mem: "); | |
Serial.print(memfree()); | |
Serial.println(); | |
} | |
updateTFTTime(timestring, newtimestring, fullUpdate); | |
memcpy(timestring, newtimestring, strlen(newtimestring) ); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Created by Moolet on 18/03/2021. | |
// | |
#include "output_spi.h" | |
/* Audio Library for Teensy 3.X | |
* Copyright (c) 2017, Paul Stoffregen, [email protected] | |
* | |
* Development of this audio library was funded by PJRC.COM, LLC by sales of | |
* Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop | |
* open source software by purchasing Teensy or other PJRC products. | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a copy | |
* of this software and associated documentation files (the "Software"), to deal | |
* in the Software without restriction, including without limitation the rights | |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
* copies of the Software, and to permit persons to whom the Software is | |
* furnished to do so, subject to the following conditions: | |
* | |
* The above copyright notice, development funding notice, and this permission | |
* notice shall be included in all copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
* THE SOFTWARE. | |
*/ | |
#include <Arduino.h> | |
#include "SPI.h" | |
#if !defined(KINETISL) | |
#include "memcpy_audio.h" | |
#include "utility/imxrt_hw.h" | |
#define AD7607_BUSY 3 | |
#define AD7607_START_CONVERSION 5 | |
#define AD7607_CHIP_SELECT 36 | |
#define AD7607_RESET 35 | |
#define AD7607_RANGE_SELECT 37 | |
#define DA_SYNC 38 | |
#define MOSI_PIN 26 | |
#define MISO_PIN 39 | |
#define SCK_PIN 27 | |
#define LRCLK_CPY 40 | |
/* AD5754R Register Map */ | |
#define AD5754R_REG_RANGE_SELECT 0x01 // Output range select register | |
/* AD5754R Channel Address */ | |
#define AD5754R_DAC_ALL 0x04 // All four DACs | |
/* AD5754R Range Bits */ | |
#define AD5754R_BIPOLAR_10_RANGE 0x04 // -10...+10(V) | |
audio_block_t * AudioOutputSPI::block_input[8] = { | |
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr | |
}; | |
bool AudioOutputSPI::update_responsibility = false; | |
DMAChannel AudioOutputSPI::dmatx(false); | |
DMAChannel AudioOutputSPI::dmarx(false); | |
//DMAMEM | |
__attribute__((aligned(32))) | |
uint32_t zeros[AUDIO_BLOCK_SAMPLES/2]; | |
//DMAMEM | |
__attribute__((aligned(32))) | |
uint8_t tdm_tx_buffer[32 * 4]; | |
volatile uint16_t AudioOutputSPI::_readIndex = 0; | |
volatile uint16_t AudioOutputSPI::_writeIndex = 0; | |
volatile bool AudioOutputSPI::_resetReceived = false; | |
audio_block_t *AudioOutputSPI::prev[8] = { | |
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr | |
}; | |
//DMAMEM | |
__attribute__((aligned(32))) | |
volatile uint8_t AudioOutputSPI::rxbuf[32] = {0}; | |
audio_block_t * AudioOutputSPI::block_incoming[8] = { | |
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr | |
}; | |
audio_block_t * AudioOutputSPI::block_write[8] = { | |
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr | |
}; | |
static const uint32_t zero_level = (0xFFFF / 2)+1; | |
void setClockDivider_noInline(uint32_t clk) | |
{ | |
static const uint32_t clk_sel[4] = { | |
664615384, // PLL3 PFD1 | |
720000000, // PLL3 PFD0 | |
528000000, // PLL2 | |
396000000}; // PLL2 PFD2 | |
uint32_t cbcmr = CCM_CBCMR; | |
uint32_t clkhz = clk_sel[(cbcmr >> 4) & 0x03] / (((cbcmr >> 26 ) & 0x07 ) + 1); // LPSPI peripheral clock | |
uint32_t d, div; | |
d = clk ? clkhz/clk : clkhz; | |
if (d && clkhz/d > clk) d++; | |
if (d > 257) d= 257; // max div | |
if (d > 2) { | |
div = d-2; | |
} else { | |
div =0; | |
} | |
uint32_t ccr = LPSPI_CCR_SCKDIV(div) | LPSPI_CCR_DBT(div/2) | LPSPI_CCR_PCSSCK(div/2); | |
//Serial.printf("SPI.setClockDivider_noInline CCR:%x TCR:%x\n", _ccr, port().TCR); | |
IMXRT_LPSPI3_S.CR = 0; | |
IMXRT_LPSPI3_S.CFGR1 = LPSPI_CFGR1_MASTER | LPSPI_CFGR1_SAMPLE; | |
IMXRT_LPSPI3_S.CCR = ccr; | |
IMXRT_LPSPI3_S.CR = LPSPI_CR_MEN; | |
} | |
void AudioOutputSPI::begin(void) | |
{ | |
Serial.begin(9600); | |
pinMode( DA_SYNC, OUTPUT); | |
digitalWrite( DA_SYNC, HIGH); | |
pinMode( AD7607_CHIP_SELECT, OUTPUT); | |
digitalWriteFast( AD7607_CHIP_SELECT, HIGH); | |
pinMode( AD7607_START_CONVERSION, OUTPUT); | |
digitalWriteFast( AD7607_START_CONVERSION, HIGH); | |
pinMode( AD7607_RESET, OUTPUT); | |
digitalWrite( AD7607_RESET, LOW); | |
pinMode( AD7607_RANGE_SELECT, OUTPUT); | |
digitalWrite( AD7607_RANGE_SELECT, HIGH); | |
pinMode( LRCLK_CPY, INPUT); | |
delayMicroseconds(10); | |
SPI1.begin(); | |
digitalWrite(DA_SYNC, LOW); | |
SPI1.beginTransaction(SPISettings()); | |
uint8_t configureDac[] = { | |
0, | |
0, | |
0x10, | |
0x00, | |
0x0f, | |
0x10, | |
0x00, | |
0x0f | |
}; | |
SPI1.transfer(configureDac, 8); | |
SPI1.endTransaction(); | |
digitalWrite(DA_SYNC, HIGH); | |
delayMicroseconds(10); | |
// Set voltage range for DAC0, DAC1; | |
digitalWrite(DA_SYNC, LOW); | |
uint8_t configureDacVoltageRange[] = { | |
0, | |
0, | |
(AD5754R_REG_RANGE_SELECT << 3) + AD5754R_DAC_ALL, | |
0x00, | |
AD5754R_BIPOLAR_10_RANGE, | |
(AD5754R_REG_RANGE_SELECT << 3) + AD5754R_DAC_ALL, | |
0x00, | |
AD5754R_BIPOLAR_10_RANGE | |
}; | |
SPI1.beginTransaction(SPISettings()); | |
SPI1.transfer(configureDacVoltageRange, 8); | |
SPI1.endTransaction(); | |
digitalWrite(DA_SYNC, HIGH); | |
delayMicroseconds(10); | |
for (int i=0; i < 8; i++) { | |
block_input[i] = nullptr; | |
} | |
memset(zeros, 0, sizeof(zeros)); | |
memset(tdm_tx_buffer, 0, sizeof(tdm_tx_buffer)); | |
dmatx.begin(true); // Allocate the DMA channel first | |
dmatx.disable(); | |
dmatx.sourceBuffer(tdm_tx_buffer, 32); | |
dmatx.transferSize(4); | |
dmatx.transferCount(8); | |
dmatx.destination((volatile uint32_t &)IMXRT_LPSPI3_S.TDR); | |
dmatx.triggerAtHardwareEvent(DMAMUX_SOURCE_LPSPI3_TX); | |
dmatx.disableOnCompletion(); | |
dmatx.interruptAtCompletion(); | |
dmatx.attachInterrupt(tx_complete_isr); | |
dmarx.begin(true); // allocate the DMA channel first | |
dmarx.disable(); | |
dmarx.destinationBuffer(rxbuf, 32); | |
dmarx.source((volatile uint32_t &)IMXRT_LPSPI3_S.RDR); | |
dmarx.transferSize(4); | |
dmarx.transferCount(8); | |
dmarx.triggerAtHardwareEvent(DMAMUX_SOURCE_LPSPI3_RX); | |
dmarx.disableOnCompletion(); | |
dmarx.attachInterrupt(rx_complete_isr); | |
dmarx.interruptAtCompletion(); | |
for (uint8_t count=0; count<4; count++) { | |
tdm_tx_buffer[(count*8)+3] = 0; | |
tdm_tx_buffer[(count*8)+2] = 0; | |
tdm_tx_buffer[(count*8)+1] = count; //DAC0, channel=count | |
tdm_tx_buffer[(count*8)+0] = 0xFF;//(block_input[count*2] != NULL) ? block_input[count*2]->data[_readIndex] >> 8 : zero_level; | |
tdm_tx_buffer[(count*8)+7] = 0xFF;//(block_input[count*2] != NULL) ? block_input[count*2]->data[_readIndex] & 0xff : zero_level; | |
tdm_tx_buffer[(count*8)+6] = count; //DAC1, channel=count | |
tdm_tx_buffer[(count*8)+5] = 0xFF;//(block_input[count*2+1] != NULL) ? block_input[count*2+1]->data[_readIndex] >> 8 : zero_level; | |
tdm_tx_buffer[(count*8)+4] = 0xFF;//(block_input[count*2+1] != NULL) ? block_input[count*2+1]->data[_readIndex] & 0xff : zero_level; | |
//DAC1, channel=count | |
} | |
SPI1.setSCK(SCK_PIN); | |
SPI1.setMOSI(MOSI_PIN); | |
SPI1.setMISO(MISO_PIN); | |
SPI1.setCS(DA_SYNC); | |
SPI1.begin(); | |
IMXRT_LPSPI3_S.TCR = (IMXRT_LPSPI3_S.TCR & ~(LPSPI_TCR_FRAMESZ(7))) | LPSPI_TCR_FRAMESZ(63) ; // Change framesize to 64 bits | |
setClockDivider_noInline(30000000); | |
digitalWriteFast(AD7607_START_CONVERSION, LOW); | |
digitalWriteFast(AD7607_START_CONVERSION, HIGH); | |
attachInterrupt(digitalPinToInterrupt(LRCLK_CPY),timer,RISING); | |
// https://forum.pjrc.com/threads/65229-Setting-up-custom-I2S-communication | |
//attachInterruptVector(IRQ_SAI1, timer); | |
//NVIC_ENABLE_IRQ(IRQ_SAI1); | |
//I2S1_TCSR |= 1<<12; // start generating TX FIFO interrupts | |
NVIC_SET_PRIORITY(IRQ_LPSPI3, 5); | |
NVIC_SET_PRIORITY(IRQ_DMA_CH0 + dmatx.channel, 10); | |
NVIC_SET_PRIORITY(IRQ_DMA_CH0 + dmarx.channel, 2); | |
NVIC_SET_PRIORITY(IRQ_GPIO6789, 1); | |
for (int i = 0; i < 8; i++) { | |
block_write[i] = allocate(); | |
if (block_write[i] == nullptr) { | |
for (int j = 0; j < i; j++) { | |
release(block_write[j]); | |
} | |
//memset(new_block, 0, sizeof(new_block)); | |
break; | |
} | |
} | |
} | |
void AudioOutputSPI::rx_complete_isr(void) { | |
dmarx.clearInterrupt(); | |
for (int i = 0; i < 8; i++) { | |
if (block_write[i] != NULL) { | |
block_write[i]->data[_writeIndex] = ((rxbuf[i*2+1] << 8) + rxbuf[i*2]); | |
} | |
} | |
_writeIndex++; | |
if (_writeIndex == 128) { | |
memcpy(block_incoming, block_write, sizeof(block_incoming)); | |
//for (int i=0; 0 < 8; i++) | |
// block_incoming[i] = block_write[i]; | |
audio_block_t *new_block[8]; | |
// allocate 8 new blocks. If any fails, allocate none | |
for (int i = 0; i < 8; i++) { | |
new_block[i] = allocate(); | |
if (new_block[i] == nullptr) { | |
for (int j = 0; j < i; j++) { | |
release(new_block[j]); | |
} | |
memset(new_block, 0, sizeof(new_block)); | |
break; | |
} | |
} | |
// __disable_irq(); | |
memcpy(block_write, new_block, sizeof(block_write)); | |
_writeIndex = 0; | |
// __enable_irq(); | |
} | |
digitalWrite(AD7607_START_CONVERSION, LOW); | |
digitalWrite(AD7607_START_CONVERSION, HIGH); | |
dmarx.TCD->SOFF = 0; | |
} | |
void AudioOutputSPI::tx_complete_isr(void) | |
{ | |
digitalWriteFast(AD7607_CHIP_SELECT, HIGH); | |
dmatx.clearInterrupt(); | |
//while (IMXRT_LPSPI3_S.FSR & 0x1f);//FIFO Status register: wait until fifo is complete | |
while (IMXRT_LPSPI3_S.SR & LPSPI_SR_MBF); //Status Register: wait until Module Busy flag is cleared | |
//delayNanoseconds(20); | |
_readIndex++; | |
if (_readIndex >= 128 && _resetReceived) { | |
_readIndex = 0; | |
for (unsigned int i=0; i < 8; i++) { | |
if (prev[i]) { | |
release(prev[i]); | |
prev[i] = nullptr; | |
} | |
} | |
_resetReceived = false; | |
} | |
} | |
void AudioOutputSPI::update(void) | |
{ | |
unsigned int i, j; | |
audio_block_t *out_block[8]; | |
__disable_irq(); | |
memcpy(out_block, block_incoming, sizeof(out_block)); | |
for (i=0; i < 8; i++) { | |
prev[i] = block_input[i]; | |
block_input[i] = receiveReadOnly(i); | |
} | |
_resetReceived = true; | |
__enable_irq(); | |
if (out_block[0] != nullptr) { | |
// if we got 1 block, all 16 are filled | |
for (i = 0; i < 8; i++) { | |
transmit(out_block[i], i); | |
release(out_block[i]); | |
} | |
} | |
/* | |
for (i=0; i < 8; i++) { | |
if (prev[i]) release(prev[i]); | |
} | |
*/ | |
} | |
void AudioOutputSPI::timer(void) { | |
const uint16_t readIndex = _readIndex; | |
if (readIndex < 128) { | |
for (uint8_t count = 0; count < 4; count++) { | |
//DAC0, channel=count | |
uint8_t doubleCount = count * 2; | |
audio_block_t *block = (_resetReceived) ? prev[doubleCount] : block_input[doubleCount]; | |
uint16_t value = (block != NULL) ? block->data[readIndex] + zero_level : zero_level; | |
tdm_tx_buffer[(count * 8) + 0] = value >> 8; | |
tdm_tx_buffer[(count * 8) + 7] = value & 0xff; | |
//tdm_tx_buffer[(count * 8) + 0] = readIndex >> 8; | |
//tdm_tx_buffer[(count * 8) + 7] = readIndex & 0xff; | |
//DAC1, channel=count | |
uint8_t doubleCountPlusOne = count * 2 + 1; | |
audio_block_t *block2 = (_resetReceived) ? prev[doubleCountPlusOne] : block_input[doubleCountPlusOne]; | |
uint16_t value2 = (block2 != NULL) ? block2->data[readIndex] + zero_level : zero_level; | |
tdm_tx_buffer[(count * 8) + 5] = value2 >> 8; | |
tdm_tx_buffer[(count * 8) + 4] = value2 & 0xff; | |
//tdm_tx_buffer[(count * 8) + 5] = readIndex >> 8; | |
//tdm_tx_buffer[(count * 8) + 4] = readIndex & 0xff; | |
//DAC1, channel=count | |
} | |
//IMXRT_LPSPI3_S.TCR = (IMXRT_LPSPI3_S.TCR & ~(LPSPI_TCR_FRAMESZ(7))) | LPSPI_TCR_FRAMESZ(63); // Change framesize to 48 bits | |
//IMXRT_LPSPI3_S.FCR = 0; | |
IMXRT_LPSPI3_S.DER = LPSPI_DER_TDDE | LPSPI_DER_RDDE; //DMA Enable register: enable DMA on TX | |
IMXRT_LPSPI3_S.SR = 0x3f00; // status register: clear out all of the other status... | |
dmarx.enable(); | |
dmatx.enable(); | |
digitalWriteFast(AD7607_CHIP_SELECT, LOW); | |
} | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Created by Moolet on 18/03/2021. | |
// | |
#ifndef TEENSYAUDIOSPISHAREDLIBRARY_OUTPUT_SPI_H | |
#define TEENSYAUDIOSPISHAREDLIBRARY_OUTPUT_SPI_H | |
#include "Arduino.h" | |
#include "AudioStream.h" | |
#include "DMAChannel.h" | |
class AudioOutputSPI : public AudioStream | |
{ | |
public: | |
AudioOutputSPI(void) : AudioStream(8, inputQueueArray) { begin(); } | |
virtual void update(void); | |
void begin(void); | |
protected: | |
static audio_block_t *block_input[8]; | |
static audio_block_t *block_incoming[8]; | |
static audio_block_t *block_write[8]; | |
static bool update_responsibility; | |
static DMAChannel dmatx; | |
static DMAChannel dmarx; | |
static void tx_complete_isr(void); | |
static void rx_complete_isr(void); | |
static void timer(void); | |
static volatile uint16_t _readIndex; | |
static volatile uint16_t _writeIndex; | |
static volatile bool _resetReceived; | |
private: | |
audio_block_t *inputQueueArray[8]; | |
static audio_block_t *prev[8]; | |
static volatile uint8_t rxbuf[32]; | |
}; | |
#endif //TEENSYAUDIOSPISHAREDLIBRARY_OUTPUT_SPI_H |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment