|
Forum Index : Microcontroller and PC projects : MMX: String corruption after PLAY FLAC
| Author | Message | ||||
| BrantB Newbie Joined: 27/10/2017 Location: CanadaPosts: 40 |
I promise, with Scout's honour, that I am not spending hours and hours specifically looking for problems . I certainly get no joy out of finding what appears to be a bug - though I am quite happy to "do my bit" and contribute in whatever way I can to the advancement of Micromite.What I have been doing over the last several days, is exercising the elements of MMX that are of particular interest to me, because I know they will be needed in the projects I tend to get involved with. I first experiment with each of these elements in isolation (using simple scenarios for initial learning), and then I typically move them into an ever-growing piece of proof-of-concept code, which brings them all together. As a result of my experiments, I am pretty sure I have stumbled over a problem with the PLAY FLAC routine. The playing itself works flawlessly - but, I think the internal 'wrap up' routine somehow stomps on string memory (regardless of whether or not the 'finished playing' interrupt is employed). This did not show up in my initial, simple, isolated experiments - because all I did was play one file, and that was it. But then, when I merged the feature into my ever-growing proof-of-concept code, strange things started to happen (including routinely getting a CPU exception, resulting in reboots). So I set about isolating the cause, and the code below is the result of trying to chase down what was happening. It has some constants which control the exact nature of the logic flow. This is because, during debugging, I pursued a few hypotheses. First, I thought the issue had to do with the use of the 'finished playing' interrupt. Not so. Then, it started to look like the problem might have been occurring (quite strangely) in a SELECT-CASE statement. Not so. Eventually, I narrowed it down to just the actual playing of the FLAC file. As I said, the playing itself works fine. The problem only appears as the track is ending; that's when string memory pointers appear to go walkabout. From what I can tell, numeric variables seem to remain unaffected - but I would not want to swear that will always be the case. OPTION EXPLICIT ' Change these constants to control how the program actually runs. ' ' USE_FLAC_DONE: ' ' 0 = Automatically advance the FLAC track every 90 seconds ' 1 = Use the FLAC "done" interrupt to advance the track ' ' USE_SELECT_CASE: ' ' 0 = Use a series of IF-THEN statements to assign FLAC filename ' 1 = Use a SELECT CASE block to assign FLAC filename ' ' ACTUALLY_PLAY: ' ' 0 = Skip the PLAY FLAC command ' (really only useful when USE_FLAC_DONE = 0 ' 1 = Issue the PLAY FLAC command CONST USE_FLAC_DONE = 0 CONST USE_SELECT_CASE = 1 CONST ACTUALLY_PLAY = 1 ' Delare all variables appropriately DIM TSEC AS INTEGER DIM TFLAC AS INTEGER DIM FLAC_PLAYING AS INTEGER DIM FLAC_TRACK AS INTEGER DIM FLAC_FILE$ AS STRING DIM TEST_STRING$ AS STRING DIM SHOW_DEBUG AS INTEGER ' Reset the Console printing interval to 0 (zero) TSEC = 0 TFLAC = 0 ' Reset the FLAC playlist variables FLAC_PLAYING = 0 FLAC_TRACK = 0 ' Reset the extra debugging flag SHOW_DEBUG = 0 ' Reset the TIMER to 0 (zero), and wait for a bit to gurantee ' that it will be >0 when the main loop starts TIMER = 0 PAUSE 5 ' --- MAIN LOOP --- DO ' If the TIMER goes past the pre-determined printing interval, ' then print its current value to the Console, and calcualte ' the next trigger value (i.e. 5 seconds hence) IF Timer > TSEC THEN TSEC = TIMER + 5000 PRINT "TIMER: "; STR$(TIMER) PRINT "TRACK: "; STR$(FLAC_TRACK) PRINT "FILE: "; FLAC_FILE$ PRINT "TEST: "; TEST_STRING$ END IF ' If we're in timed track mode (rather than using the DONE interrupt), ' then we have some work to do here if USE_FLAC_DONE = 0 THEN ' If the TIMER goes past the pre-determined track interval, ' then reset the playing flag (to force a track change), and ' calculate the next trigger value (i.e., 90 seconds hence) IF TIMER > TFLAC THEN 'Only show the debug info at the Track 1 -> Track 2 transition IF (TFLAC > 80000) AND (TFLAC < 100000) THEN SHOW_DEBUG = 1 END IF TFLAC = TIMER + 90000 FLAC_PLAYING = 0 END IF END IF ' Only process the FLAC playlist if nothing is currently playing IF FLAC_PLAYING = 0 THEN ' Print some debug info to show how key variables behave IF SHOW_DEBUG = 1 THEN PRINT " DEBUG 1 - TRACK: "; STR$(FLAC_TRACK) PRINT " DEBUG 1 - FILE: "; FLAC_FILE$ PRINT " DEBUG 1 - TEST: "; TEST_STRING$ END IF ' Advance the track number; wrap it around to 1 at the end FLAC_TRACK = FLAC_TRACK + 1 IF FLAC_TRACK > 2 THEN FLAC_TRACK = 1 END IF ' Print some debug info to show how key variables behave IF SHOW_DEBUG = 1 THEN PRINT " DEBUG 2 - TRACK: "; STR$(FLAC_TRACK) PRINT " DEBUG 2 - FILE: "; FLAC_FILE$ PRINT " DEBUG 2 - TEST: "; TEST_STRING$ END IF ' Based on the track number, assign an actual filename to play ' ' NOTE: The exact method used to traslate the track number ' into a filename, depends on how one of our constants is set. ' We will either use (the nicer) SELECT-CASE method, or instead, ' use a series of IF-THEN's. IF USE_SELECT_CASE = 1 THEN SELECT CASE FLAC_TRACK CASE 1 FLAC_FILE$ = "\111.FLAC" TEST_STRING$ = "TRACK ONE" CASE 2 FLAC_FILE$ = "\125.FLAC" TEST_STRING$ = "TRACK TWO" CASE ELSE FLAC_FILE$ = "" TEST STRING = "NO TRACK" END SELECT ELSE FLAC_FILE$ = "" TEST_STRING$ = "NO TRACK" IF FLAC_TRACK = 1 THEN FLAC_FILE$ = "\111.FLAC" TEST_STRING$ = "TRACK ONE" END IF IF FLAC_TRACK = 2 THEN FLAC_FILE$ = "\125.FLAC" TEST_STRING$ = "TRACK TWO" END IF END IF ' Print some debug info to show how key variables behave IF SHOW_DEBUG = 1 THEN PRINT " DEBUG 3 - TRACK: "; STR$(FLAC_TRACK) PRINT " DEBUG 3 - FILE: "; FLAC_FILE$ PRINT " DEBUG 3 - TEST: "; TEST_STRING$ END IF ' Only process the filename if it is valid IF FLAC_FILE$ <> "" THEN ' Set the flag to indicate that we're busy playing tunes FLAC_PLAYING = 1 ' Play the file (either with, or with the interrupt feature, ' depending on the mode selected by our constants). if USE_FLAC_DONE = 1 THEN ' Only issue the PLAY command, if our constants tell us to IF ACTUALLY_PLAY = 1 THEN PLAY FLAC FLAC_FILE$, INT_FLAC_DONE END IF ELSE ' Only issue the PLAY command, if our constants tell us to IF ACTUALLY_PLAY = 1 THEN PLAY FLAC FLAC_FILE$ END IF END IF ' Print to the Console, the name of what we are playing PRINT "Playing: ";FLAC_FILE$ END IF ' Print some debug info to show how key variables behave IF SHOW_DEBUG = 1 THEN PRINT " DEBUG 4 - TRACK: "; STR$(FLAC_TRACK) PRINT " DEBUG 4 - FILE: "; FLAC_FILE$ PRINT " DEBUG 4 - TEST: "; TEST_STRING$ SHOW_DEBUG = 0 END IF end if ' Automatically quit after 5 minutes (300,000ms) LOOP UNTIL TIMER > 300000 ' --- END of MAIN LOOP --- ' Ensure current track is stopped (no harm if it already is) PLAY STOP ' INTERRUPT - Triggers when FLAC playback is complete SUB INT_FLAC_DONE ' Update the flag to show that we are no longer busy FLAC_PLAYING = 0 SHOW_DEBUG = 1 ' Give a nod to the Console PRINT "FLAC DONE!" END SUB END I was originally going to attach a ZIP containing the two FLAC files that I used for experimenting (just in case it has something do to with the specific data stream - though, unlikely), as well as some debug output - but the ZIP (at 17MB) was going to exceed size limits for the forum. 2018-03-09_061330_FLAC_Debug_Output.zip So, I have only ZIPped the debug output (no FLAC files) for the following two scenarios: CONST USE_FLAC_DONE = 0 CONST USE_SELECT_CASE = 1 CONST ACTUALLY_PLAY = 0 ... and: CONST USE_FLAC_DONE = 0 CONST USE_SELECT_CASE = 1 CONST ACTUALLY_PLAY = 1 In the two lots of debug output, I have manually added the text *****TRANSITION***** where ever the program/output should be moving from one FLAC track to another. This will allow anyone investigating/duplicating this to quickly jump to the more "interesting" sections of the output - in order to see/verify results. In the case where the PLAY command is actually used, pay particular attention to the first *****TRANSITION***** event (from track 1 to 2). Note how, just before the ending of the first track, the debug info shows as follows: TIMER: 85163 TRACK: 1 FILE: \111.FLAC TEST: TRACK ONE ... but after the 1st track has ended, and the code has tried to update the variables to play the 2nd track, the debug info shows as follows: TIMER: 90164 TRACK: 1 FILE: FILE: TEST: LAC_TRACK Note the info highlighted in red. That's a problem; nothing in the code assigns those values. (Those look more like string constants and/or parts of variable names.) The FILE: item should show as \125.FLAC, and the TEST: item should show as TRACK TWO.I suspect this is something that @matherp will need to look at. CPU: PIC32MZ2048EFH100 (200Mhz) MMX: v5.0414 Cheers, Brant |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10569 |
Does the same thing happen playing WAV files? On the MMX and the MM+? |
||||
| BrantB Newbie Joined: 27/10/2017 Location: CanadaPosts: 40 |
Ah, I cannot answer that at this point. I don't have an MM+ environment to test on, and have not yet rigged up my MMX environment to hear WAV playback. That latter point brings me to another question, though. In the most recent version of the MMX manual, pin 6 (for 100pin CPU) is shown as PWM-2C and SOUND-LEFT. I can accept that (although, I would have expected it on 2A). But SOUND-RIGHT is shown on pin 18 - and that pin does not appear to have a PWM facility. PWM-2B is shown on pin 40. So ... my question is ... what is the correct way to wire things up for WAV playback on a 100pin MMX? Armed with that, I should be able to at least provide you with an answer to that unknown. (Unfortunately, physical re-wiring will now have to wait until tomorrow, as I have to head home for a hot meal - lest I disrupt domestic harmony .) |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10569 |
As per the manual - sound is not related to PWM except that in the 100-pin I ran out of unallocated pins that were capable of the function. If you look at the 144-pin sound and PWM pin usage don't overlap. It is set to PWM2C so you can still use 1A and 1B for normal PWM |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10569 |
Please try the attached - seems to fix it for me (not sure why though )2018-03-09_212459_MMX5.04.14.zip |
||||
| BrantB Newbie Joined: 27/10/2017 Location: CanadaPosts: 40 |
I tried your update (I was VERY careful to make sure I was flashing the correct firmware this time, so as to ensure that I avoided that embarrassment again ), and it seems to have fixed it for me too .I exercised various combinations of its use (i.e., with and without the 'done' interrupt, etc.) in the isolated test program, and all results were good. I then also tried it in my ever-growing proof-of-concept program, and it performed well in that scenario too. Many thanks for the quick fix. (And if you are not sure why this works, a mere mortal like me stands no chance whatsoever !)I would like to be very careful with regards to how I go about pursing my next inquiry. I am very sensitive to the fact that I am still a newbie around here, and I assure you there is no complaint, challenge, or any other such negative connotation intended here. (Ah, the disadvantages of the written word, as opposed to a live conversation.) What did I miss? Where/How could I have determined for myself that WAV playback is not related to PWM (other than the happenstance of pin allocation)? I certainly don't want to be asking questions for which there are already published answers ... and the last thing I want to do is give the impression that I don't put any effort into reading through the manuals (and/or other threads) before posting in the forum. I am definitely not "that" guy (every forum has one ... or more). But, to be brutally honest (without any offence intended), following the manuals can be a little bit confusing at times. I have the impression that the Plus manual only covers whatever is not already covered in the "standard" manual, and that the eXtreme manual only covers what is not already covered in the other two, combined. Is that a fair assessment? (If not, I need to know - so I don't perpetuate my confusion .)Using that approach, I reviewed the Plus manual to learn about WAV playback - and there, it talks about PWM channel 2, the 80KHz carrier frequency, low pass filter, implications to the SERVO command, etc. Nothing in the eXtreme manual seemed to suggest that the methodology was any different in MMX. So, I was left with the distinct impression that the WAV playback was dependent upon the PWM signals. Did I somehow totally misinterpret the manual(s)? If so, my apologies. BTW - I have some other things to exercise today, with my MMX rig remaining wired as it currently is. However, over the weekend, I will adjust it for WAV playback (as per the MMX manual) and test/confirm that aspect of your update as well. (And, of course, I will report back to this thread.) Again, many thanks for the fix (and for all that you do). Cheers! |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10569 |
There was no intention to be pejorative in my reply, I was just pointing out that the pin allocation in the manual was correct. The long answer is much more complex PWM and sound both make use of the output compare function in the PIC. Only certain pins are capable of this and moreover for each pin that is there is only one or two timers that can be used to clock it. The PIC32MZ has slightly more flexibility than the PIC32MX. So on the 144-pin I can have 3 output compare channels on each of two clocks and still have a timer and two channels available for sound. On the 100-pin I've got the three timers but have run out of pins to have 8 individual output compare channels. The pin used for PWM-2C can use either the sound clock or the PWM2 clock. If you use sound it is allocated to that clock and if you use it for PWM it is allocated to the PWM clock. This can only really be fully understood by reading the PIC manual so MMBasic tries to hide that sort of detail. The manuals do build up as you say and it does make it somewhat difficult but other than any missed errors in the manuals if a pin is allocated to a particular function then it can be used for that function and will only interact with other defined uses of that specific pin unless specifically documented Don't know if this helps - confuses me just writing it |
||||
| BrantB Newbie Joined: 27/10/2017 Location: CanadaPosts: 40 |
Well, why didn't you just say so in the first place ... we could have avoided all of that. Okay, seriously ... I do appreciate your explanation. I have a character flaw for which I blame (er, uh, credit) my parents - "knowing" something is all well and good, but understanding it is even better. Now that I have a bit better understanding of the WAV/(non-)PWM circumstances, it makes much more sense to me. (And I didn't read any snark into your initial response ... I just wondered how I had managed to miss the mark so terribly . All good.) |
||||
| BrantB Newbie Joined: 27/10/2017 Location: CanadaPosts: 40 |
For the sake of completeness (and to follow through on the promise I made), I have now tested the behaviour of the WAV playback - both in the earlier firmware (in which the FLAC playback issue was first discovered), and in the most recent version (in which it was fixed). Last things first - WAV playback works just fine in the latest/fixed firmware. Interestingly, though, it turns out that the WAV playback also works (worked) just fine in the older firmware too. In other words, the WAV playback apparently never did cause any string corruption. Hmm. @matherp - I know you mentioned you weren't quite sure why your fix works ... but, are these results consistent with whatever you changed? Or does this now make the issue even more confusing? |
||||
| The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |