Phatline

store 16bit variable to 8bit FILE_Writebuffer

34 posts in this topic

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

Share this post


Link to post
Share on other sites

:blush: 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 by Phatline

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

...
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:
fetch.php?media=antichambre:capture_d_e_

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 by Antichambre

Share this post


Link to post
Share on other sites

oups!
change

MIOS32_DOUT_PinSet( 59, (edit>>1) & 1);

to

MIOS32_DOUT_PinSet( 59, (edit>>3) & 1);

Share this post


Link to post
Share on other sites
if(edit & 0x0f)memcpy(&loop_copy, &loop[track], sizeof loop_copy);   

clever i like that :happy:


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 :cheers: happy new sun year, skol!

Share this post


Link to post
Share on other sites
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 by Antichambre

Share this post


Link to post
Share on other sites

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 by Phatline

Share this post


Link to post
Share on other sites
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 !!! :cheers:
Bruno

Edited by Antichambre
1 person likes this

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now