Jump to content

So many questions....


jsflint
 Share

Recommended Posts

Hi everybody!

After a long time I decided to try out my midiboxing skills...

I just started coding yesterday and I have no experience whatsoever with this.. So please be nice... Additionally I have not yet started building the damn thing so many of my questions will probably be solved when switching it on the first time. But I'm afraid I'll fry it up ;)

Anyway, I need a lot of help with my code cause I have no freakin idea if anything I coded is correct... But before I post the respective code snippets I will try to describe what my small midi box should do in the end and post a picture so you know what I have in mind...

midi.jpg

The box is going to act as a floorboard controller for my guitar effects rig. Although I have some commercial controllers I thought they could do better for my purposes so I ended up here  ;)

The box has 6 buttons (DIN 0x00 - 0x05 sorry for the typo in the pic) and two external inputs for buttons (DIN 0x6 and 0x7).

Buttons 4-6 send Control Changes; Button 1 switches between 2 Program Changes (for the distorted guitar channel), same goes for Button 2 (for the clean guitar channel). Button 3 is a shift button, that switches between 3 banks. The Program Changes of Buttons 1 and 2 act correspondingly.

External Button 2 sends a Control Change message, Ext Button 1 is a little bit more complicated. It is somehow a remote control for Button 1 and 2. It switches between the two Program Change messages of these Buttons, dependent on the last pressed Button (which channel is selected).

The LEDs 0x07 - 0xA are regular LEDs. The first 3 light up when Control Changes are received, LED 0xA ist just a status LED that turns on, when the midibox is on.

The lower row of LEDs should be RGB Leds that light up in a different color, when the corresponding button is pressed.

So far for the concept.... Now comes the really big part, a million questions (I have read the wiki and the forum but still need help, since I'm really a newbie at this...Sorry).

The whole main.c (WIP) can be downloaded at hxxp://www.dailymojo.org/main.zip if it is easier for you...

I'll continue now by posting code snippets and then asking the questions for this part, ok?

Alright...

/////////////////////////////////////////////////////////////////////////////

// Local variables

/////////////////////////////////////////////////////////////////////////////

// last_button + shift + dirty lead + clean lead + ext1

unsigned char last_button;

unsigned char shift;

unsigned char dirty;

unsigned char clean;

unsigned char ext1;

/////////////////////////////////////////////////////////////////////////////

// This function is called by MIOS after startup to initialize the

// application

/////////////////////////////////////////////////////////////////////////////

void Init(void) __wparam

{

  // set shift register update frequency

  MIOS_SRIO_UpdateFrqSet(1); // ms

  // we need to set at least one IO shift register pair

  MIOS_SRIO_NumberSet(NUMBER_OF_SRIO);

  // debouncing value for DINs

  MIOS_SRIO_DebounceSet(DIN_DEBOUNCE_VALUE);

  MIOS_SRIO_TS_SensitivitySet(DIN_TS_SENSITIVITY);

  // only one DOUTX4 module is connected

  // the maximum value is 16 (-> 128 digital outputs)

  MIOS_SRIO_NumberSet(16);

 

  // intialize start-up status etc

  MIOS_DOUT_PinSet(0xA, 1); // Status LED

  MIOS_DOUT_PinSet(0x00, 1); // LED Dirty Rhythm On

  MIOS_DOUT_PinSet(0x01, 0); // Other Channel LEDs off

  MIOS_DOUT_PinSet(0x02, 0);

  MIOS_DOUT_PinSet(0x03, 0);

  MIOS_MIDI_BeginStream();

  MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 16

  MIOS_MIDI_TxBufferPut(0x1 + shift);  // ProgramChange 1 + shift DIRTY RHYTHM EQ

  MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 1

  MIOS_MIDI_TxBufferPut(0x59);  // ProgramChange 89

  MIOS_MIDI_TxBufferPut(0xC1); // Midichannel 2

  MIOS_MIDI_TxBufferPut(0x0);  // ProgramChange 0

  MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f); // High-Active State

  MIOS_MIDI_EndStream();

  last_button = 0;

}

The first 'couple' of questions:

1) Do I have to declare the local variables somewhere else as well? (total C noob question..)

2) In the void Init part I included my personal start-up status. Does this belong here or after the void init function?

3) As I stated above, I want to use RGB LEDs to make it cooler-looking. In the code I treat every color of the LED as a single DOUT, is this the correct way?

4) Whatfor is the MIOS_MIDI_BeginStream command? In some examples this command was left out... I included it anyway..

5) Is this the correct way to send multiple midi messages at once? As you can see I send three messages simutaneously...

6) In the beginning I introduced the char 'shift' , which indicates the status of the shift button (see above). Now in my first midi out message (and in some others too) I want to send a Program Change command which is "ProgChange 1 + shift value" but I don't know if this is the correct way, probably not since I add a decimal value to the Hex value..

7) the last line shall set the last_button char value as a 0, is this correct?

Ok, this was the first part, many of these commands will come up again and again so ignore them in the next code parts...

/////////////////////////////////////////////////////////////////////////////

//  This function is called by MIOS when a complete MIDI event has been received

/////////////////////////////////////////////////////////////////////////////

void MPROC_NotifyReceivedEvnt(

  unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam

{

  // BLOCK STATUS RECEIVE -> LED 4-6

  if( evnt0 == 0xBF ) {

// evnt0 == 0xBF  = Control Change on MidiChannel 16

    if( evnt2 == 0x00 ) {

      // Control Change Value 0

      MIOS_DOUT_PinSet(evnt1 +=6, 0);

  } else {

      // Control Change Value 127

      MIOS_DOUT_PinSet(evnt1 +=6, 1);

    }

  }

}

The corresponding DOUT_PinSet value should be the received Control Change Number (evnt1) + a decimal 6 (as you can see above the LEDs that should react to these messages are 0x07 to 0x09, so I want to add a 6 to the cc number). How do I do that?

Ok, the next part describes what happens if a button is pressed... I tried to code it the most easiest way I could (or as I could learn from this forum) but due to my inability to code in C there are probably some errors.. I have no specific questions here, please just have a look at it (especially case 0x06 - is there an easier way to do this?) and tell me if I should jump from a bridge or if there is someway to make me a midiboxer ;)

/////////////////////////////////////////////////////////////////////////////

// This function is called by MIOS when an button has been toggled

// pin_value is 1 when button released, and 0 when button pressed

/////////////////////////////////////////////////////////////////////////////

void DIN_NotifyToggle(unsigned char pin, unsigned char pin_value) __wparam

{

switch( pin ) {

  case 0x02: // Bank Button as a Shift button to toggle between three equalizer modes

  shift++;

  if(shift > 2) { shift = 0; }

    switch(shift) {

  case 0:

    MIOS_DOUT_PinSet(0x04, 1);

        MIOS_DOUT_PinSet(0x05, 0);

        MIOS_DOUT_PinSet(0x06, 0);

      break;

  case 1:

    MIOS_DOUT_PinSet(0x04, 0);

        MIOS_DOUT_PinSet(0x05, 1);

        MIOS_DOUT_PinSet(0x06, 0);

  break;

  case 2:

    MIOS_DOUT_PinSet(0x04, 0);

        MIOS_DOUT_PinSet(0x05, 0);

        MIOS_DOUT_PinSet(0x06, 1);

      break;

} // switch shift

  case 0x00: // Dirty Rhythm/Lead

  dirty++;

  if(dirty >1) {dirty = 0}

    switch(dirty) {

  case 0:

  MIOS_DOUT_PinSet(0x00, 1); // LED Dirty Rhythm On

  MIOS_DOUT_PinSet(0x01, 0); // Other Channel LEDs off

  MIOS_DOUT_PinSet(0x02, 0);

  MIOS_DOUT_PinSet(0x03, 0);

      MIOS_MIDI_BeginStream();

      MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 16

      MIOS_MIDI_TxBufferPut(0x1 + shift);  // ProgramChange 1 + shift DIRTY RHYTHM EQ

      MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 1

      MIOS_MIDI_TxBufferPut(0x59);  // ProgramChange 89

      MIOS_MIDI_TxBufferPut(0xC1); // Midichannel 2

      MIOS_MIDI_TxBufferPut(0x0);  // ProgramChange 0

      MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f); // High-Active State

      MIOS_MIDI_EndStream();

  last_button = 0;

      break;

  case 1:

  MIOS_DOUT_PinSet(0x00, 0); // LED Dirty Lead On

  MIOS_DOUT_PinSet(0x01, 1); // Other Channel LEDs off

  MIOS_DOUT_PinSet(0x02, 0);

  MIOS_DOUT_PinSet(0x03, 0);

  MIOS_MIDI_BeginStream();

      MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 16

      MIOS_MIDI_TxBufferPut(0x7 + shift);  // ProgramChange 7 + shift DIRTY LEAD EQ

      MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 1

      MIOS_MIDI_TxBufferPut(0x7E);  // ProgramChange 126

      MIOS_MIDI_TxBufferPut(0xC1); // Midichannel 2

      MIOS_MIDI_TxBufferPut(0x0);  // ProgramChange 0 EVENTUELL ÄNDERN WEGEN LOOPER AUF 1

      MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f); // High-Active State

      MIOS_MIDI_EndStream();

  last_button = 1;

      break;

  } // switch dirty

 

  case 0x01: // Clean Rhythm/Lead

  clean++;

  if(clean >1) {clean = 0}

    switch(clean) {

  case 0:

  MIOS_DOUT_PinSet(0x00, 0); // LED Clean Rhythm On

  MIOS_DOUT_PinSet(0x01, 0); // Other Channel LEDs off

  MIOS_DOUT_PinSet(0x02, 1);

  MIOS_DOUT_PinSet(0x03, 0);

      MIOS_MIDI_BeginStream();

      MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 16

      MIOS_MIDI_TxBufferPut(0x44 + shift);  // ProgramChange 4 + shift Clean RHYTHM EQ

      MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 1

      MIOS_MIDI_TxBufferPut(0x59);  // ProgramChange 89

      MIOS_MIDI_TxBufferPut(0xC1); // Midichannel 2

      MIOS_MIDI_TxBufferPut(0x1);  // ProgramChange 1 EVENTUELL ÄNDERN WEGEN LOOPER AUF 2

      MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f); // High-Active State

      MIOS_MIDI_EndStream();

  last_button = 2;

      break;

  case 1:

  MIOS_DOUT_PinSet(0x00, 0); // LED Clean Lead On

  MIOS_DOUT_PinSet(0x01, 0); // Other Channel LEDs off

  MIOS_DOUT_PinSet(0x02, 0);

  MIOS_DOUT_PinSet(0x03, 1);

  MIOS_MIDI_BeginStream();

      MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 16

      MIOS_MIDI_TxBufferPut(0xA + shift);  // ProgramChange 10 + shift Clean LEAD EQ

      MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 1

      MIOS_MIDI_TxBufferPut(0x77);  // ProgramChange 119

      MIOS_MIDI_TxBufferPut(0xC1); // Midichannel 2

      MIOS_MIDI_TxBufferPut(0x1);  // ProgramChange 1 EVENTUELL ÄNDERN WEGEN LOOPER AUF 3

      MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f); // High-Active State

      MIOS_MIDI_EndStream();

  last_button = 3;

      break;

  } // switch clean

 

  case 0x03: // Harmonizer Function Switch 1

  MIOS_MIDI_BeginStream();

  MIOS_MIDI_TxBufferPut(0xBF); // CC on channel 16

  MIOS_MIDI_TxBufferPut(0x1);  // CC #1

  MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f); // Velocity = 0x7f when

                                                  // button pressed, else 0x00

  MIOS_MIDI_EndStream();

  break;

 

  case 0x04: // Tremolo Function Switch 2

  MIOS_MIDI_BeginStream();

  MIOS_MIDI_TxBufferPut(0xBF); // CC on channel 16

  MIOS_MIDI_TxBufferPut(0x2);  // CC #2

  MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f); // Velocity = 0x7f when

                                                  // button pressed, else 0x00

  MIOS_MIDI_EndStream();

  break;

 

  case 0x05: // Tuner Function Switch 3

  MIOS_MIDI_BeginStream();

  MIOS_MIDI_TxBufferPut(0xBF); // CC on channel 16

  MIOS_MIDI_TxBufferPut(0x3);  // CC #3

  MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f); // Velocity = 0x7f when

                                                  // button pressed, else 0x00

  MIOS_MIDI_EndStream();

  break;

 

  case 0x06: // External Switch 1 switches between Lead and Rhythm Sound for both channels

  ext1++;

  if(ext1 >1) {ext1 = 0}

    switch(ext1) {

  case 0:

if (last_button == 0 || last_button == 1) {

MIOS_DOUT_PinSet(0x00, 1); // LED Dirty Rhythm On

MIOS_DOUT_PinSet(0x01, 0); // Other Channel LEDs off

MIOS_DOUT_PinSet(0x02, 0);

MIOS_DOUT_PinSet(0x03, 0);

MIOS_MIDI_BeginStream();

MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 16

MIOS_MIDI_TxBufferPut(0x1 + shift);  // ProgramChange 1 + shift DIRTY RHYTHM EQ

MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 1

MIOS_MIDI_TxBufferPut(0x59);  // ProgramChange 89

MIOS_MIDI_TxBufferPut(0xC1); // Midichannel 2

MIOS_MIDI_TxBufferPut(0x0);  // ProgramChange 0

MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f); // High-Active State

MIOS_MIDI_EndStream();

} // endif lastbutton

if (last_button == 2 || last_button == 3) {

MIOS_DOUT_PinSet(0x00, 0); // LED Clean Rhythm On

MIOS_DOUT_PinSet(0x01, 0); // Other Channel LEDs off

MIOS_DOUT_PinSet(0x02, 1);

MIOS_DOUT_PinSet(0x03, 0);

MIOS_MIDI_BeginStream();

MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 16

MIOS_MIDI_TxBufferPut(0x4 + shift);  // ProgramChange 4 + shift Clean RHYTHM EQ

MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 1

MIOS_MIDI_TxBufferPut(0x59);  // ProgramChange 89

MIOS_MIDI_TxBufferPut(0xC1); // Midichannel 2

MIOS_MIDI_TxBufferPut(0x1);  // ProgramChange 1 EVENTUELL ÄNDERN WEGEN LOOPER AUF 2

MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f); // High-Active State

MIOS_MIDI_EndStream();

} // endif lastbutton

break;

case 1:

if (last_button == 0 || last_button == 1) {

MIOS_DOUT_PinSet(0x00, 0); // LED Dirty Lead On

MIOS_DOUT_PinSet(0x01, 1); // Other Channel LEDs off

MIOS_DOUT_PinSet(0x02, 0);

MIOS_DOUT_PinSet(0x03, 0);

MIOS_MIDI_BeginStream();

MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 16

MIOS_MIDI_TxBufferPut(0x7 + shift);  // ProgramChange 7 + shift DIRTY LEAD EQ

MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 1

MIOS_MIDI_TxBufferPut(0x7E);  // ProgramChange 126

MIOS_MIDI_TxBufferPut(0xC1); // Midichannel 2

MIOS_MIDI_TxBufferPut(0x0);  // ProgramChange 0

MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f); // High-Active State

MIOS_MIDI_EndStream();

} // endif lastbutton

if (last_button == 2 || last_button == 3) {

MIOS_DOUT_PinSet(0x00, 0); // LED Clean Lead On

MIOS_DOUT_PinSet(0x01, 0); // Other Channel LEDs off

MIOS_DOUT_PinSet(0x02, 0);

MIOS_DOUT_PinSet(0x03, 1);

MIOS_MIDI_BeginStream();

MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 16

MIOS_MIDI_TxBufferPut(0xA + shift);  // ProgramChange 10 + shift Clean RHYTHM EQ

MIOS_MIDI_TxBufferPut(0xC0); // Midichannel 1

MIOS_MIDI_TxBufferPut(0x77);  // ProgramChange 119

MIOS_MIDI_TxBufferPut(0xC1); // Midichannel 2

MIOS_MIDI_TxBufferPut(0x1);  // ProgramChange 1 EVENTUELL ÄNDERN WEGEN LOOPER AUF 2

MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f); // High-Active State

MIOS_MIDI_EndStream();

} // endif lastbutton

break;

 

  } // switch ext1

case 0x07: // Externeal switch 2 switches Delay ON/OFF via CC #4

MIOS_MIDI_BeginStream();

MIOS_MIDI_TxBufferPut(0xBF); // CC on channel #16

MIOS_MIDI_TxBufferPut(0x4);  // CC #4

MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f); // Velocity = 0x7f when

                                                  // button pressed, else 0x00

MIOS_MIDI_EndStream();

break;

  } // switch pin

} // void din notify toggle

Ok, this was a long post and I know it's not that polite to start here with a million questions etc... But I tried to do as much as I can without asking (by reading the forum, the wiki and stuff) and now this is the part that seems unclear to me..

I tried to explain my code as precise as I can, so feel free to ask if you need something explained more in detail...

Anyway, thanks to anyone who's able one or more questions! Sorry for my english...

Well I owe you a beer or two...

Thanks,

JSF

Link to comment
Share on other sites

Hey mate :)

1) No

2) Its fine there.

3) Yes

4) That's for Midibox Link. You won't need those but they won't hurt.

5) Yes

6) Adding dec and hex is fine

7) Yes

I didn't go over your code too heavily, most of it looks OK, I would suggest loading it up and going from there :) Don't be afraid :)

One bit of advice with the switch statements, instead of

case m

blah

blah

blah

case n

blah

blah

blah

do

case m

dosomething()

case n

dosomethingelse()

oh and instead of case 1 and case 0, you can just use an if statement... It should make for cleaner code but I really don't think it will make much difference in this simple controller as it should have ample cycles available :)

Link to comment
Share on other sites

What do you mean by dosomething()?

stryd means, that the asm code generated by sdcc is smaller if you call functions from a switch case. but I don't think it makes any difference here – it may even get a bit more complicated for you, 'cause there's more to type. I don't think you really need to care about this level of optimisation for the purpose of your application; the PIC won't be overloaded with 8 knobs and 8 leds ;)

(of course it can't hurt having heard about things like these...)

cheers,

Michael

Link to comment
Share on other sites

Oh.. I got than one now... (had to look in an online C reference.. ;) ) but I think it's really a little bit to much for this small controller..

But thanks for your help! (I will probably continue asking some questions when my midibox parts arrive so... be warned!!)

Link to comment
Share on other sites

but I think it's really a little bit to much for this small controller..

stryd means, that the asm code generated by sdcc is smaller if you call functions from a switch case.

Well, there is that too... but I was more concerned with the number of temp registers it'll generate.

but I don't think it makes any difference here – it may even get a bit more complicated for you, 'cause there's more to type. I don't think you really need to care about this level of optimisation for the purpose of your application; the PIC won't be overloaded with 8 knobs and 8 leds ;)

(of course it can't hurt having heard about things like these...)

Don't forget the Too many switch cases crashes MIOS? thread :) The problem here was not in fact the number of cases... it was all the for loops inside them.

Simple way to find out though: Compile it, and count how many r0x*** registers you can see in the output file.

Link to comment
Share on other sites

Simple way to find out though: Compile it, and count how many r0x*** registers you can see in the output file.

hm, how may r0x*** registers may there be?

Does that mean, if too much temp registers are needed, it won't fit into the available RAM?

(Background: I have about 40 swich cases in a nested "super-"switch case and can see r0x0C right at the beginning of the function in the .asm file (_output). 13 r0x***es don't seem much for the incredible amount of C-Code I wrote there...

sorry stryd, if this question is somehow dumb, but if you go into details, I wanna know it really detailed  :-*  ;)

@jsflint: don't want to confuse you, sorry :)

Link to comment
Share on other sites

Thanks for all your help... as you can see I have no idea about C at all but I'm willing to learn so I follow your 'expert' discussion...

But at least I'm proud of myself 'cause I really looked at the C forum for a couple of hours and was able to write a little code... So thanks to all the midiboxers who wrote all the tutorials and stuff...

I'll try to learn more about functions and incorporate them so that the code for my small app will at least look clean...

Oh, one more question: as I won't include AINs, AOUTs and LCD etc, do I need to delete the parts from the skeleton or just leave them?

Thanks,

JSF

Link to comment
Share on other sites

Thanks for all your help... as you can see I have no idea about C at all but I'm willing to learn so I follow your 'expert' discussion...

Hahahah I would use the term expert very lightly in my case  ;D

But at least I'm proud of myself 'cause I really looked at the C forum for a couple of hours and was able to write a little code... So thanks to all the midiboxers who wrote all the tutorials and stuff...

I'll try to learn more about functions and incorporate them so that the code for my small app will at least look clean...

You should be proud, that's very good work for a newbie!! :)

Oh, one more question: as I won't include AINs, AOUTs and LCD etc, do I need to delete the parts from the skeleton or just leave them?

Nah just leave em empty

Ok, I tried to compile it with Xcode on mac, but, as I've never done it before, I don't know if I've done it correct, just followed the instructions on the forum.. Where shall I look for the r0x entries?

audiocommander has written a tutorial for xcode on the wiki, I would definitely check that out...

When you run the makefile, it will generate an 'output' directory, and there will be .asm files in there... at least that's it on a PC... :-\

Link to comment
Share on other sites

SDCC generates ASM-files in the "_output" directory. So whenever there's a problem, you can find the ASM here: _output/myfilename.asm

In your case, you can upload it on the chip and see if it works. You might inspect the details only if you encounter any problems.

Edit: beaten by stryd  :P

@stryd: have you seen my question about the number of rx0***'s ?

Link to comment
Share on other sites

xcode still says permission denied when I try to compile the makefile target.

you don't need to go to the bin-folder for the makefile generator.

There's just a perl script (tools/mkmk.pl) involved.

So, you should make sure that these files are:

- readable: yourproject/MAKEFILE.SPEC

- executeable: yourproject/tools/mkmk.pl

does this help?

Link to comment
Share on other sites

Hmmm.. obviously I did something wrong... somewhere... this is what I get when I try to compile the makefile target:

/Users/jsflint/Desktop/midibox/build/midibox.build/Debug/Makefile.build/Script-84A65F450BD38FD20080FE2C.sh: line 6: ./mkmk.pl: Permission denied

Link to comment
Share on other sites

hm, how may r0x*** registers may there be?

Does that mean, if too much temp registers are needed, it won't fit into the available RAM?

(Background: I have about 40 swich cases in a nested "super-"switch case and can see r0x0C right at the beginning of the function in the .asm file (_output). 13 r0x***es don't seem much for the incredible amount of C-Code I wrote there...

sorry stryd, if this question is somehow dumb, but if you go into details, I wanna know it really detailed  :-*  ;)

@jsflint: don't want to confuse you, sorry :)

Detailed it is then... This kinda goes round in a circle before it gets to the answer.... :-\ Sorry...

The r0x*** registers are used by SDCC as temporary variables within a function, the compiler decides where they are needed, and locates them in the Access Bank of ram on the PIC. The advantage of that, is that the access bank can be read or written, without the need for any additional instructions, whereas the remaining ram must be accessed either in banked or indirect mode.

Banked operations require you to select the current memory bank prior to accessing the variable, you'll see those as BANKSEL in your ASM files (or SETBSR in TK's). Banksel is a macro which is substituted for the necessary command depending on PIC model - in our case I think BANKSEL MyBank becomes MOVLB MyBank. Note that it is a 2 word instruction (in order to carry enough data for the memory pointer). After that, you can read and write the variables only within that bank. If you go to a different bank, you need a new banksel. SDCC actually puts a banksel in every time, and the optimiser removes the unecessary ones.

Indirect operations require you to load a memory pointer called the File Select Register or FSR. There are 3 of them, FSR0 FSR1 and FSR2, and they're a 14-bit pointer, so there is a low byte, and high byte of which only 6 bits are used. So you calculate the address to your variable, load it into FSRxH(5:0) and FSRxL, and the contents of that location are then available by reading or writing registers like INDFx and POSTDECx (which reads from the location and then decrements the address of the pointer).

In order to access these variables like INDFx without needing a bank selection (which would obviously not work with other banked memory) they are also stored in the access bank. They are known as Special Function Registers or SFRs (not to be confused with FSR like I did hehehe). SFRs are registers used by the CPU and peripheral modules for controlling the PIC. Stuff like the timer registers, status bits, I/O ports (TRISx, PORTx etc) are all SFRs as well. The acces bank is actually split in two. All of these SFRs are stored in Access Bank High, which is located right at the top of the RAM. You can see it in the linker:

ACCESSBANK NAME=accesssfr  START=0xF80          END=0xFFF          PROTECTED
Table 5-2 in thee 4620 datasheet lists all the SFRs with a brief description. You probably know most of them already. Access Ram Low, which is at 0x000, is available for our applications. MIOS variables take up the first 16 bytes, and then 0x010 to 0x07F is free. You can see that memory described in the lkr as so:
DATABANK   NAME=miosvars   START=0x000          END=0x00f
ACCESSBANK NAME=accessram  START=0x010          END=0x07F
The MIOSVars are reserved by the wrapper am file :
MIOS_VARIABLES		udata	0x0000
_MIOS_BOX_CFG0		res	1
_MIOS_BOX_CFG1		res	1
_MIOS_BOX_STAT		res	1
_MIOS_PARAMETER1	res	1
_MIOS_PARAMETER2	res	1
_MIOS_PARAMETER3	res	1
_TMP1			res	1
_TMP2			res	1
_TMP3			res	1
_TMP4			res	1
_TMP5			res	1
_IRQ_TMP1		res	1
_IRQ_TMP2		res	1
_IRQ_TMP3		res	1
_IRQ_TMP4		res	1
_IRQ_TMP5		res	1
And you can see them in the .map file:
MIOS_VARIABLES      udata   00000000       data   0x000010
              Chances are, the very next line in your .map file will be this:
.registers      udata   0x000010       data   0x000038
And that's our friend, the r0x*** registers from SDCC. These registers were the result of this ASM file from sneakthief's seq:
; Internal registers
.registers	udata_ovr	0x010
r0x00	res	1
r0x01	res	1
r0x02	res	1
r0x03	res	1
r0x04	res	1
r0x05	res	1
r0x06	res	1
r0x07	res	1
r0x08	res	1
r0x09	res	1
r0x0A	res	1
r0x0B	res	1
r0x0C	res	1
r0x0D	res	1
r0x0E	res	1
r0x0F	res	1
r0x10	res	1
r0x11	res	1
r0x12	res	1
r0x13	res	1
r0x14	res	1
r0x15	res	1
r0x16	res	1
r0x17	res	1
r0x18	res	1
r0x19	res	1
r0x1A	res	1
r0x1B	res	1
r0x1C	res	1
r0x1D	res	1
r0x1E	res	1
r0x1F	res	1
r0x20	res	1
r0x21	res	1
r0x22	res	1
r0x23	res	1
r0x24	res	1
r0x25	res	1
r0x26	res	1
r0x27	res	1
r0x28	res	1
r0x29	res	1
r0x2A	res	1
r0x2B	res	1
r0x2C	res	1
r0x2D	res	1
r0x2E	res	1
r0x2F	res	1
r0x30	res	1
r0x31	res	1
r0x32	res	1
r0x33	res	1
r0x34	res	1
r0x35	res	1
r0x36	res	1
r0x37	res	1

You can see from the linker above that they can go up to  END=0x07F, so in theory, we could have 0x6F (111) of them.

Putting that theory into practice however, was not so successful in the case of sneakthief's seq. Because the variables are used as 'scratch space', they are often reused within a function. That app was using them as counters in for loops among ather things, and when that app got to r0x037 (it's last register) and tried to re-use r0x000 again, the thing went berserk and crashed the PIC.

I suspect that this was actually a bug in SDCCs code, so maybe we can get away with it, maybe not... but it's the kind of thing that's often better off cleaned up anyway...

Did that make any sense at all? :-\

Edit: Trivia - the PICs with CAN and USB peripherals have too many SFRs, and some of them are located in the upper regions of banked RAM, not in access ram. I don't know why I mention that ;D

Link to comment
Share on other sites

Did that make any sense at all?

Absolutely! cheers for explaining this!

r0x37 is indeed ...wooo, quite a number...

As mentioned, in the kII Midi-Receive Function, I have mixed simple calls, if-statements and very long sub-switches (eg. [tt]switch(msgType) { case MIDI_CC: switch(MIDI_CC) { case CCBankselect: ...[/tt] )

I counted roughly 40 to 50 cases alone for the CC case statement (sub-switch-routine), and I found just 13 r0x*** registers. that's good, eh'?  8)

Great to know about that,

thanks again, stryd :)

Link to comment
Share on other sites

I counted roughly 40 to 50 cases alone for the CC case statement (sub-switch-routine), and I found just 13 r0x*** registers. that's good, eh'?  8)

That is good :)

Glad I could make sense. Sorry jsflint, if I were you, all that would probably make me go "WTF" right now! Just ignore us  ;D

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...