From ad6a1848edc3e547691199e5baffe30e3f33702f Mon Sep 17 00:00:00 2001 From: Florian Rau Date: Tue, 9 Aug 2022 23:48:14 +0200 Subject: [PATCH] wrapping things up for the first alpha --- README.md | 2 +- SynkinoLC_EAGLE/.gitignore | 2 + SynkinoLC_Firmware/SynkinoLC/audio.cpp | 99 +++++++++++++++++++------- SynkinoLC_Firmware/SynkinoLC/audio.h | 10 ++- 4 files changed, 86 insertions(+), 27 deletions(-) create mode 100644 SynkinoLC_EAGLE/.gitignore diff --git a/README.md b/README.md index a6c2226..7bd2165 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ You'll need the following components to assemble SynkinoLC: | 1 | [Texas Instruments SN74AHC14N](https://octopart.com/sn74ahc14n-texas+instruments-465338) | inverted Schmitt-trigger | | 2 | [SparkFun ROB-09453](https://octopart.com/rob-09453-sparkfun-67069573) | line sensor breakout (analog) | | 1 | [Bourns PEC11L-4215F-S0015](https://octopart.com/pec11l-4215f-s0015-bourns-25517430) | rotary encoder | -| 1 | [Cliff CL170849BR](https://octopart.com/cl170849br-cliff-22810934) (or similar) | knob for rotary encoder | +| 1 | [Cliff CL170842CR](https://octopart.com/cl170842cr-cliff-22810928) (or similar) | knob for rotary encoder | | 1 | [TDK PS1240P02BT](https://octopart.com/ps1240p02bt-tdk-8602108) | piezo buzzer | | 2 | [CUI Devices SJ1-2503A](https://octopart.com/sj1-2503a-cui+devices-106235597) | 2.5mm audio jack | | 2 | [Tensility CA-2203](https://octopart.com/ca-2203-tensility-19254819) (or similar) | 2.5mm audio cable, stereo | diff --git a/SynkinoLC_EAGLE/.gitignore b/SynkinoLC_EAGLE/.gitignore new file mode 100644 index 0000000..2079fe6 --- /dev/null +++ b/SynkinoLC_EAGLE/.gitignore @@ -0,0 +1,2 @@ +*.s#* +*.b#* diff --git a/SynkinoLC_Firmware/SynkinoLC/audio.cpp b/SynkinoLC_Firmware/SynkinoLC/audio.cpp index 1b79b95..c70cb37 100644 --- a/SynkinoLC_Firmware/SynkinoLC/audio.cpp +++ b/SynkinoLC_Firmware/SynkinoLC/audio.cpp @@ -53,7 +53,10 @@ using namespace TeensyTimerTool; #define WAIT_FOR_STARTMARK 2 #define START 3 #define PLAYING 4 -#define SHUTDOWN 250 +#define PAUSE 5 +#define PAUSED 6 +#define RESUME 7 +#define SHUTDOWN 254 #define QUIT 255 extern UI ui; @@ -61,16 +64,7 @@ extern Projector projector; bool runPID = false; PeriodicTimer pidTimer(TCK); - -// PID -volatile unsigned long totalImpCounter = 0; -int32_t syncOffsetImps = 0; -bool sampleCountRegisterValid = true; -unsigned long sampleCountBaseLine = 0; - -unsigned int impToSamplerateFactor; -int deltaToFramesDivider; -unsigned int impToAudioSecondsDivider; +volatile uint32_t totalImpCounter = 0; // Constructor Audio::Audio() : Adafruit_VS1053_FilePlayer{VS1053_RST, VS1053_CS, VS1053_DCS, VS1053_DREQ, VS1053_SDCS} { @@ -189,14 +183,9 @@ bool Audio::selectTrack() { delay(500); // wait for pause setVolume(4,4); // raise volume back up for playback - impToSamplerateFactor = _fsPhysical / _fps / pConf.shutterBladeCount; - deltaToFramesDivider = _fsPhysical / _fps; + impToSamplerateFactor = _fsPhysical / _fps / pConf.shutterBladeCount; + deltaToFramesDivider = _fsPhysical / _fps; impToAudioSecondsDivider = _fps * pConf.shutterBladeCount; - // pausePlaying(false); - // while (true) { - // delay(100); - // PRINTF("%d kbps\n", getBitrate()); - // } // 4. Prepare PID myPID.SetMode(myPID.Control::timer); @@ -260,12 +249,32 @@ bool Audio::selectTrack() { if (runPID) { speedControlPID(); runPID = false; + state = handlePause(); } drawPlayingMenu(); - if (!playingMusic) + if (stopped()) state = SHUTDOWN; break; + case PAUSE: + pausePlaying(true); + PRINTLN("Paused Playback."); + pidTimer.stop(); + state = PAUSED; + break; + + case PAUSED: + drawPlayingMenu(); + state = handlePause(); + break; + + case RESUME: + pausePlaying(false); + PRINTLN("Resumed Playback."); + pidTimer.start(); + state = PLAYING; + break; + case SHUTDOWN: stopPlaying(); PRINTLN("Stopped Playback."); @@ -273,9 +282,49 @@ bool Audio::selectTrack() { state = QUIT; } } + u8g2->setFont(FONT10); return true; } +uint8_t Audio::handlePause() { + static uint16_t pauseDetectedPeriod = (1000 / _fps * 3); + static uint32_t prevTotalImpCounter = 0; + static uint32_t lastImpMillis; + + bool impsChanged = (totalImpCounter + syncOffsetImps) != prevTotalImpCounter; + + if (paused()) { + if (impsChanged) + return RESUME; + else + return PAUSED; + } else { + if (impsChanged && !paused()) { + prevTotalImpCounter = totalImpCounter + syncOffsetImps; + lastImpMillis = millis(); + } else if ((millis() - lastImpMillis) >= pauseDetectedPeriod) { + //lastSampleCounterHaltPos = Read32BitsFromSCI(0x1800); + //myPID.SetMode(MANUAL); + //lastImpCounterHaltPos = totalImpCounter + syncOffsetImps; + return PAUSE; + } + return PLAYING; + } +} + +// uint8_t Audio::waitForResumeToPlay(unsigned long impCounterStopPos) { +// static uint32_t prevTotalImpCounter = 0; +// if ((totalImpCounter + syncOffsetImps) == impCounterStopPos) { +// return; +// } else { +// myPID.SetMode(AUTOMATIC); +// restoreSampleCounter(lastSampleCounterHaltPos); +// musicPlayer.resumeMusic(); +// tellFrontend(CMD_PROJ_PLAY, 0); +// myState = PLAYING; +// } +// } + void Audio::speedControlPID() { uint32_t actualSampleCount = getSampleCount() - sampleCountBaseLine; int32_t desiredSampleCount = (totalImpCounter + syncOffsetImps) * impToSamplerateFactor; @@ -309,11 +358,11 @@ void Audio::drawPlayingMenuConstants() { u8g2->setFont(FONT10); } -void Audio::drawPlayingMenuStatus(bool isPlaying) { - if (isPlaying) - u8g2->drawXBMP(60, 54, play_xbm_width, play_xbm_height, play_xbm_bits); - else +void Audio::drawPlayingMenuStatus() { + if (paused()) u8g2->drawXBMP(60, 54, pause_xbm_width, pause_xbm_height, pause_xbm_bits); + else + u8g2->drawXBMP(60, 54, play_xbm_width, play_xbm_height, play_xbm_bits); } void Audio::drawWaitForPlayingMenu() { @@ -321,7 +370,7 @@ void Audio::drawWaitForPlayingMenu() { drawPlayingMenuConstants(); ui.drawCenteredStr(28, "Waiting for"); ui.drawCenteredStr(46, "Film to Start"); - drawPlayingMenuStatus(false); + drawPlayingMenuStatus(); u8g2->sendBuffer(); } @@ -354,7 +403,7 @@ void Audio::drawPlayingMenu() { if (ss < 10) u8g2->print("0"); u8g2->print(ss); - // drawPlayingMenuStatus(!projectorPaused); + drawPlayingMenuStatus(); // draw sync status if (_frameOffset == 0) diff --git a/SynkinoLC_Firmware/SynkinoLC/audio.h b/SynkinoLC_Firmware/SynkinoLC/audio.h index f2511ae..d25e247 100644 --- a/SynkinoLC_Firmware/SynkinoLC/audio.h +++ b/SynkinoLC_Firmware/SynkinoLC/audio.h @@ -15,12 +15,19 @@ class Audio : public Adafruit_VS1053_FilePlayer { private: QuickPID myPID = QuickPID(&Input, &Output, &Setpoint); float Setpoint, Input, Output; + uint16_t _fsPhysical = 0; char _filename[11] = {0}; uint8_t _fps = 0; uint16_t _trackNum = 0; int32_t _frameOffset = 0; + int32_t syncOffsetImps = 0; + uint32_t sampleCountBaseLine = 0; + uint16_t impToSamplerateFactor; + uint16_t deltaToFramesDivider; + uint16_t impToAudioSecondsDivider; + bool loadPatch(); void enableResampler(); void adjustSamplerate(signed long ppm2); @@ -30,13 +37,14 @@ class Audio : public Adafruit_VS1053_FilePlayer { void restoreSampleCounter(uint32_t samplecounter); int32_t average(int32_t); void speedControlPID(); + uint8_t handlePause(); static bool connected(); uint16_t selectTrackScreen(); uint32_t getSampleCount(); void drawPlayingMenuConstants(); void drawWaitForPlayingMenu(); void drawPlayingMenu(); - void drawPlayingMenuStatus(bool); + void drawPlayingMenuStatus(); bool loadTrack(); uint16_t getSamplingRate(); uint16_t getBitrate();