Hawkeye Posted December 20, 2017 Report Share Posted December 20, 2017 Hi, in this line is the problem with the failed initialization, can you find it? :-) Quote for ( a=0; a>8; a++ ) { Regarding the identical file-sizes for two different structs: the structs look good. You could output the value of sizeof(store_t) either to your LCD or as a MIOS debug message to the MIOS terminal - i bet the value looks good and it is a problem with the file writing code. Also make sure, you've recompiled the structure definition file after changing the structure size, if the linker links to an old object file, the sizeof calculation may be wrong. Regarding background tasks - which data are you calculating, and how often do you need to recalculate it? The core is really quite fast, in the loopa context for example, i can output/calculate on something like 16kbytes in every screen refresh cycle (something like 30-50hz). I've "hooked" the screen output routine to an xtask and it works nicely without overloading the rest of the system. If you change data, that is used in other threads/tasks, you need to protect by a mutex though. It is a bit of an advanced topic, that's why i ask why you cannot calculate in the main task of the running app/sequencer. Many greets, Peter Quote Link to comment Share on other sites More sharing options...
Phatline Posted December 20, 2017 Author Report Share Posted December 20, 2017 (edited) aja a < 8 of course, thx! Edit: read/write on SD-Card is working fine! MUTEX_SDCARD_TAKE; //Write to File sprintf(file_path, "msp/%d-%d.msp", track, clip); FILE_WriteOpen ( file_path, 16 ); FILE_WriteBuffer( (u8 *)&file_type, 4 ); FILE_WriteBuffer( (u8 *)&loop[track], sizeof(store_t) ); FILE_WriteClose (); MUTEX_SDCARD_GIVE; @ Background-tasks function example which make a hardfault when using 1024, when calling it... i call it once a time with a button press on the UI (DIN) > see code below but also will need such things for mooving sequencer data forward in loop, or backwards, or copy step 0-15 to all other 512 steps in a musically way > means could be a wild button orgie... in App.h: typedef struct storage { // to optimize SD-Load-Time, each clips data is stored in this struct u16 PB [512]; // Pitchband inital = 8192 = No Pitchbend! u8 SEQ[512] [8]; // 512Steps, 8NotePolyphony u8 MSQ[512]; // Motion-SEQ of one CC ...eg.:Control-Wheel of Keyboard char leader; // Programchange able? - only 1 of 4 Song-Clips can send Programchanges via BLMatrix char virgin; // is there any data in the clip? need to display on a ButtonLed Matrix-Launcher u8 length; // 1x16, 2x16... u8 decay; // 60ms... could be set with Encoder, but I dont need a variable, since the melody out will be used by the Triggermatrix... u8 rythm; // 4x4=16, 5x3=15 usw... to calculate maximal duration per UI-matrix page u16 bpm; } store_t; extern store_t loop[8]; in app.c: u16 SEQ_copy[512][8] = {{}}; //Copy actual Track into ClipboardBuffer u16 MSQ_copy[512] = {}; //Copy actual Track into ClipboardBuffer u16 PB_copy [512] = {}; //Copy actual Track into ClipboardBuffer u16 tact_info_copy[32] = {}; //Copy bpm, loop length, tact and so on // E D I T C L I P D A T A static void Edit_Clip(u8 track, u16 clip, u16 job){ u16 c = 0; u16 x = 0; switch(job) { // Clear case 0: for( c=0; c<512; c++ ) { if(edit[0] == 1) { loop[track].PB[c] = 8192; } // = no Pitch Bend if(edit[1] == 1) {for( x=0; x<8; x++ ) { loop[track].SEQ[c][x] = 0; } } // = no Note if(edit[2] == 1) {loop[track].MSQ[c] = 0; } // = no Control Change } break; // Copy case 1: for( c=0; c<512; c++ ) { if(edit[0] == 1) { PB_copy[c] = loop[track].PB[c];} // PB if(edit[1] == 1) { for( x=0; x<8; x++ ) { SEQ_copy[c][x] = loop[track].SEQ[c][x]; } } // NOTE if(edit[2] == 1) { MSQ_copy[c] = loop[track].MSQ[c];} // MSQ } if(edit[3] == 1) { tact_info_copy[0] = loop[track].leader; tact_info_copy[1] = loop[track].virgin; tact_info_copy[2] = loop[track].length; tact_info_copy[3] = loop[track].decay; tact_info_copy[4] = loop[track].rythm; tact_info_copy[5] = loop[track].bpm; } break; // Paste case 2: for( c=0; c<512; c++ ) { if(edit[0] == 1) { loop[track].PB[c] = PB_copy[c];} // PB if(edit[1] == 1) { for( x=0; x<8; x++ ) { loop[track].SEQ[c][x] = SEQ_copy[c][x]; } } // NOTE if(edit[2] == 1) { loop[track].MSQ[c] = MSQ_copy[c]; } // MSQ } if(edit[3] == 1) { loop[track].leader = tact_info_copy[0]; loop[track].virgin = tact_info_copy[1]; loop[track].length = tact_info_copy[2]; loop[track].decay = tact_info_copy[3]; loop[track].rythm = tact_info_copy[4]; loop[track].bpm = tact_info_copy[5]; } break; } } also the code above is working ifne ;) Edited December 20, 2017 by Phatline Quote Link to comment Share on other sites More sharing options...
Hawkeye Posted December 20, 2017 Report Share Posted December 20, 2017 Good to see, that there is progress! :-) I can't check the whole code, but there might be out-of-bound memory accesses somewhere, that will usually result in a crash sooner or later. It might just work with an array size of 512, but would crash when using 1024, welcome to the beauty of C :-). You need to double-check all write-accesses (indices). A good strategy here is to "comment out code", and see when the problem stops. Then look at the commented out segment and subdivide it, comment out more, you should be able to find it like that. Also regarding speed, as you are only doing small assignment loops up to 1024 or 512x8 or so, this is easily fast enough to be executed on a button press, for that there is no need of a background task. You could even do this every sequencer tick or so in the main thread and it would still probably be fast enough - multithreading just adds even more difficult to detect problems, avoid it for now if you can. Many greets and good luck! Peter Quote Link to comment Share on other sites More sharing options...
Antichambre Posted December 21, 2017 Report Share Posted December 21, 2017 (edited) ... sorry I was on the way back home... But Peter was here. This is what I propose you, I compile it successfully and call Edit function from App_Background without any Hardfault, I verify reset and copy subfunction by SendDebugMessage... All is fine. your whole modified project: http://www.midibox.org/dokuwiki/lib/exe/fetch.php?media=phatline:seq-melody-footboard_copie.zip in details: first better to use same struct as clipboard: //Card-Clip-Container store_t loop[8]; store_t loop_copy; //instead of // u16 SEQ_copy[512][8] = {{}}; //Copy actual Track into ClipboardBuffer // u16 MSQ_copy[512] = {}; //Copy actual Track into ClipboardBuffer // u16 PB_copy [512] = {}; //Copy actual Track into ClipboardBuffer // u16 tact_info_copy[32] = {}; //Copy bpm, loop length, tact and so on better using bits for edit flags, you will understand why after: // char edit[4] = {1,1,1,1}; //PB, SEQ, MSQ, Beatstructure, Edit Flags for copy paste clear u8 edit = 0xff; //PB, SEQ, MSQ, Beatstructure, Edit Flags for copy paste clear to initialise your tracks in APP_Init: //initalize 8 Tracks with standard values u8 a; edit= 0x0f; for ( a=0; a<8; a++ )Edit_Clip(a, 0, 0); This is what I did to check edit function at startup: void APP_Background(void){ #ifdef APP_EDIT_TEST edit= 0x0f; Edit_Clip(0, 0, 1); u16 c, x; for( c=0; c<512; c++ ) { MIOS32_MIDI_SendDebugMessage("PB: %d: %d to %d.", c, loop[0].PB[c] ,loop_copy.PB[c]); for(x=0; x<8; x++)MIOS32_MIDI_SendDebugMessage("SEQ: %d: %d to %d.", c, loop[0].SEQ[c][x] ,loop_copy.SEQ[c][x]); MIOS32_MIDI_SendDebugMessage("MSQ: %d: %d to %d.", c, loop[0].MSQ[c] ,loop_copy.MSQ[c]); MIOS32_MIDI_SendDebugMessage("leader: %d: %d to %d.", c, loop[0].leader,loop_copy.leader); MIOS32_MIDI_SendDebugMessage("virgin: %d: %d to %d.", c, loop[0].virgin,loop_copy.virgin); MIOS32_MIDI_SendDebugMessage("length: %d: %d to %d.", c, loop[0].length, loop_copy.length); MIOS32_MIDI_SendDebugMessage("decay: %d: %d to %d.", c, loop[0].decay, loop_copy.decay); MIOS32_MIDI_SendDebugMessage("rythm: %d: %d to %d.", c, loop[0].rythm, loop_copy.rythm); MIOS32_MIDI_SendDebugMessage("bpm: %d: %d to %d.", c, loop[0].bpm, loop_copy.bpm); } #endif // endless loop while( 1 ) {} } Result: Working with edit bits flags, You have to verify this cause I haven't got the necessary hardware. - In APP_SRIO_ServicePrepare MIOS32_DOUT_PinSet( 56, edit & 0x01); MIOS32_DOUT_PinSet( 57, (edit>>1) & 1); MIOS32_DOUT_PinSet( 58, (edit>>2) & 1); MIOS32_DOUT_PinSet( 59, (edit>>1) & 1); //instead of // MIOS32_DOUT_PinSet( 56, edit[0]); // MIOS32_DOUT_PinSet( 57, edit[1]); // MIOS32_DOUT_PinSet( 58, edit[2]); // MIOS32_DOUT_PinSet( 59, edit[3]); - In APP_DIN_NotifyToggle case 8: edit ^= (1<<0); break; // Act on: PB case 9: edit ^= (1<<1); break; // Act on: SEQ case 10: edit ^= (1<<2); break; // Act on: MSQ-CC case 11: edit ^= (1<<3); break; // Act on: Beat structure like Loop Length BPM and so on //instead of // case 8: edit[0] =! edit[0]; break; // Act on: PB // case 9: edit[1] =! edit[1]; break; // Act on: SEQ // case 10: edit[2] =! edit[2]; break; // Act on: MSQ-CC // case 11: edit[3] =! edit[3]; break; // Act on: Beat structure like Loop Length BPM and so on Now this is your modified edit function: Note: better to remove clip variable if you do not use it // E D I T C L I P D A T A static void Edit_Clip(u8 track, u16 clip, u16 job){ // clip is not used in this procedure better to remove it ;) switch(job) { // Reset(Clear) case 0: if(edit & (1<<0))wmemset(loop[track].PB, (u32)((8192<<16) + 8192), (sizeof (loop[track].PB))/4); // reset Pitch Bend if(edit & (1<<1))memset(loop[track].SEQ, 0, sizeof loop[track].SEQ); // reset Note if(edit & (1<<2))memset(loop[track].MSQ, 0, sizeof loop[track].MSQ); // reset Control Change if(edit & (1<<3)){ // reset track parameters loop[track].leader = 0; loop[track].virgin = 1; loop[track].length = 1; loop[track].decay = 60; //maximal 256 since we use u8 integer type loop[track].rythm = 4; loop[track].bpm = 120; } break; // Copy case 1: if(edit & 0x0f)memcpy(&loop_copy, &loop[track], sizeof loop_copy); // copy full track else{ if(edit & (1<<0))memcpy(loop_copy.PB, loop[track].PB, sizeof loop_copy.PB); // copy Pitch Bend if(edit & (1<<1))memcpy(loop_copy.SEQ, loop[track].SEQ, sizeof loop_copy.SEQ); // copy Note if(edit & (1<<2))memcpy(loop_copy.MSQ, loop[track].MSQ, sizeof loop_copy.MSQ); // copy Control Change if(edit & (1<<3)){ // copy track parameters loop_copy.leader = loop[track].leader; loop_copy.virgin = loop[track].virgin; loop_copy.length = loop[track].length; loop_copy.decay = loop[track].decay; loop_copy.rythm = loop[track].rythm; loop_copy.bpm = loop[track].bpm; } } break; // Paste case 2: if(edit & 0x0f)memcpy(&loop[track], &loop_copy, sizeof loop_copy); // paste full track else{ if(edit & (1<<0))memcpy(loop[track].PB, loop_copy.PB, sizeof loop[track].PB); // paste Pitch Bend if(edit & (1<<1))memcpy(loop[track].SEQ, loop_copy.SEQ, sizeof loop[track].SEQ); // paste Note if(edit & (1<<2))memcpy(loop[track].MSQ, loop_copy.MSQ, sizeof loop[track].MSQ); // paste Control Change if(edit & (1<<3)){ // paste track parameters loop[track].leader = loop_copy.leader; loop[track].virgin = loop_copy.virgin; loop[track].length = loop_copy.length; loop[track].decay = loop_copy.decay; loop[track].rythm = loop_copy.rythm; loop[track].bpm = loop_copy.bpm; } } break; } } This must be faster, as you can see, if edit has bit 0 to 3 @1 then the whole track will be copied or pasted in one unique memcpy ;) Voilà! Edited December 21, 2017 by Antichambre Quote Link to comment Share on other sites More sharing options...
Antichambre Posted December 21, 2017 Report Share Posted December 21, 2017 oups! change MIOS32_DOUT_PinSet( 59, (edit>>1) & 1); to MIOS32_DOUT_PinSet( 59, (edit>>3) & 1); Quote Link to comment Share on other sites More sharing options...
Phatline Posted December 21, 2017 Author Report Share Posted December 21, 2017 if(edit & 0x0f)memcpy(&loop_copy, &loop[track], sizeof loop_copy); clever i like that but i planned it more like: check which things have to copyied, so i can copy PB+NOTES, but not CC+Loop-Information, (for default) if i get it right: in your thought i can always copy only one thing: PB, All, Notes or Loop-Info but i can still use memcpy with for example: if( (edit[0]==1) && (edit[1]==1) && (edit[1]==1) && (edit[1]==1) ) memcpy(&loop_copy, &loop[track], sizeof loop_copy); THX for your help guys! for the rest i will take me time on 23.12... today we make fire in the snow, and celebrate the 21.12 to restart the sun-circle happy new sun year, skol! Quote Link to comment Share on other sites More sharing options...
Antichambre Posted December 21, 2017 Report Share Posted December 21, 2017 (edited) 5 hours ago, Phatline said: but i planned it more like: check which things have to copyied, so i can copy PB+NOTES, but not CC+Loop-Information, (for default) if i get it right: in your thought i can always copy only one thing: PB, All, Notes or Loop-Info but i can still use memcpy with for example: if( (edit[0]==1) && (edit[1]==1) && (edit[1]==1) && (edit[1]==1) ) memcpy(&loop_copy, &loop[track], sizeof loop_copy); if (edit & 0x03) then you will copy only PB + Notes and at the same time, using bits is just a better way to detect if the whole track has to be copied and using memcpy only one time, for other values it's the same as you did before. "happy new sun year" to you too ;) best Bruno Edited December 21, 2017 by Antichambre Quote Link to comment Share on other sites More sharing options...
Phatline Posted December 24, 2017 Author Report Share Posted December 24, 2017 (edited) hm i get a error: app.c:1094:13: warning: implicit declaration of function 'wmemset' [-Wimplicit-function-declaration] if(edit & (1<<0))wmemset(loop[track].PB, (u32)((8192<<16) + 8192), (sizeof (loop[track].PB))/4); // reset Pitch Bend when i then add: #include <wchar.h> to app.c then error: Quote app.c:1169:13: warning: passing argument 1 of 'wmemset' from incompatible pointer type [enabled by default] In file included from app.c:23:0: /home/triggermatrix/mios32_toolchain/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/include/wchar.h:108:10: note: expected 'wchar_t *' but argument is of type 'u16 *' should i change this: typedef struct storage { u16 PB [512]; u8 SEQ[512] [8]; u8 MSQ[512]; char leader:1; char virgin:1; u8 length; u8 decay; u8 rythm; u16 bpm; } store_t; to this: typedef struct storage { wchar_t PB PB [512]; u8 SEQ[512] [8]; u8 MSQ[512]; char leader:1; char virgin:1; u8 length; u8 decay; u8 rythm; u16 bpm; } store_t; hm what size has this wchar_t? Edited December 24, 2017 by Phatline Quote Link to comment Share on other sites More sharing options...
Antichambre Posted December 24, 2017 Report Share Posted December 24, 2017 (edited) 19 minutes ago, Phatline said: hm i get a error: app.c:1094:13: warning: implicit declaration of function 'wmemset' [-Wimplicit-function-declaration] if(edit & (1<<0))wmemset(loop[track].PB, (u32)((8192<<16) + 8192), (sizeof (loop[track].PB))/4); // reset Pitch Bend This is just a warning, it works... But ok to be sure... Don't change your structure. Just include the wchar.h library and add a (wchar_t *) to wmemset address target: if(edit & (1<<0))wmemset((wchar_t *)loop[track].PB, (u32)((8192<<16) + 8192), (sizeof (loop[track].PB))/4); // reset Pitch Bend Normally no more warning and it must work... 22 minutes ago, Phatline said: hm what size has this wchar_t? wchar_t size depends on the machine and compiler... But 4 bytes wide, 32 bits here, that's the reason sizeof is divided by 4. Joyeux Noel !!! Bruno Edited December 25, 2017 by Antichambre 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.