BoostC question.. AddressOf

Status
Not open for further replies.

Mike - K8LH

Well-Known Member
I've read through the BoostC User Manual and searched the SourceBoost Forum but can't find an answer to the question(s);

Is there a BoostC instruction that will duplicate this pair of assembly instructions (for 12F683)? Or is it possible to define a constant that's equal to the 8 bit address of the led[] array?

Code:
;
        movlw   _led            ; address of led[] array
        movwf   _ledndx         ; save address in ledptr variable
;
I'd like to replace the two assembly instructions in the ISR code below with a single C instruction that does the same thing (and also only uses two assembly instructions);
Code:
    if(column == 6)              // if all 5 columns updated
    {
      column = 0;                // reset column number
      asm
      {
        movlw   _led
        movwf   _ledndx
      }
    }
    fsr = ledndx;               // indirect access to led array
    dc0 = indf;                 // row 0 (gp0) pwm value, 0..31
    fsr++;                      //
    dc1 = indf;                 // row 1 (gp1) pwm value, 0..31
    fsr++;                      //
    dc2 = indf;                 // row 2 (gp2) pwm value, 0..31
    fsr++;                      //
    dc3 = indf;                 // row 3 (gp4) pwm value, 0..31
    ledndx = fsr + 1;           // save array index
Thanks in advance. Mike
 
Isn't that kind of thing done with pointers in C?
 
I've tried pointers but couldn't get them to work with the fsr = ledndx instruction and the ledndx = fsr + 1 instruction.

led[] is a 20 byte array of type unsigned char. I'd just like a constant or something that will work with the following three instructions;

ledndx = "8 bit address of the led[] array"; // to reset my ledndx address at end-of-scan

fsr = ledndx;

ledndx = fsr;
 
Last edited:
I should mention that I've tried pointers using code like this;

Code:
unsigned char dc0;
unsigned char dc1;
unsigned char dc2;
unsigned char dc3;

char *addr = &led;                // address of led[] array
dc0 = *addr++;                    //
dc1 = *addr++;                    //
dc2 = *addr++;                    //
dc3 = *addr++;                    //
The problem is that the addr variable seems to have been promoted to type int and the increment operations all use three assembler instructions instead of one. So each of the last four lines above uses 7 cycles instead of the 3 cycles that I'm getting from the code in post #1. Heck, a plain old dc0 = led[i++] instruction uses 7 cycles.

I just don't have the cycles to spare in this very tight ISR code.

How do you experts do it?

Mike
 
Last edited:
Use cast operator to force them back to unsigned char ?
 
Last edited:
How do I do that? If I've come across examples of that I probably didn't recognize them.

<added>

But then I'm not sure that would really help because the code in the first post is pretty efficient, using only three assembler instructions to update each of those dcx variables. So.... still looking for a single C instruction that produces two assembler instructions;
Code:
ledndx = 8_bit_address_of_led_array;
 
Last edited:
How do I do that? If I've come across examples of that I probably didn't recognize them.

Now you are asking me think about pointers and that gives me a headache.

First the problem.

char *addr = &led;

The type of addr is pointer to char. The size of this is not char but the address size, thinking 16 bit. The address of led (&led) will have the same size.

So it is natural that the compiler use 16 bits for addr. It is the address of a char and not a char.

A cast looks like this.
char A;
int B;
A= (unsigned char)B;

which works so long a the value in B will fit in a char.

You can do
(unsigned char) &led
to get a an 8 bit address for led.

char addr = (unsigned char) &led;

Now you have an 8 bit var addr.

Check to see what
dc0 = *addr++;
compiles to.

I may have missed a step.
I do not have BoostC but I think this looks like standard stuff. Still when you get into types the compilers vary.
But I could give it a try if it does not work.
Or Pommie could show us the light
 
Last edited:
casts can do the job but if you've properly declared the variables, there is no need. Plus, you have a bug in your code which is probably what you are seeing. This compiles with out errors:
Code:
char a[10];

int main(){

    char *b;

    b = a;      // note there is no need for &
    b = &a[0];  // this is the same as the previous line
   }
Note that a is the address of the array. &a is undefined. &a[0] is the address of the first element of the array.
 
Last edited:
philba,

Thank you. I tried the following variations and all produced the same code. Same problem; pointer is 16 bit and takes too many instruction cycles and I can't copy the pointer into FSR in my ISR.

Code:
char *addr;
addr = led;         // produces 4 assembler instructions

char *addr;
addr = &led;        // produces 4 assembler instructions

char *addr;
addr = &led[0];     // produces 4 assembler instructions

dc0 = addr++;       // produces 7 instructions


fsr = addr;   // <-- error, can't assign char* to char
3v0,

Your explanation and example has helped me more than all the reading and experimenting I've done today. Thank you...

Code:
char addr = (unsigned char) &led;  // still produces 4 instructions

dc0 = *addr++;      // better, 5 instructions, addr++ is an 8 bit inc'

fsr = addr;         // this assignment works now, yippee!!!
Still way too many instruction cycles so I'm going to stick with my routine but at least I have a C instruction to replace those two assembly instructions (though it costs me 2 extra assembly instructions and cycles) and I don't have a type mismatch when I copy the address into FSR.

Code:
  if(end_of_period)         // if all 32 pwm steps complete
  {                         // setup for a new column
    dcy = 0;                // reset duty cycle counter
    colpos <<= 1;           // shift column bit mask

    if(end_of_cycle)        // if all 5 columns have been updated     2/3 cyc
    {
      colpos = 1;           // reset colpos and addr variables        2 cyc
      addr = (unsigned char) &led;                                    4 cyc
    }
    shadow = 0b00010111;    // setup shadow (all row bits "on")       2 cyc
    gpio = colpos;          // setup output latch, only 1 bit high    2 cyc
    fsr = addr;             // setup row pwm variables                2 cyc
    dc0 = indf;             // row 0 (gp0) pwm value, 0..31           2 cyc
    fsr++;                  //                                        1 cyc
    dc1 = indf;             // row 1 (gp1) pwm value, 0..31           2 cyc
    fsr++;                  //                                        1 cyc
    dc2 = indf;             // row 2 (gp2) pwm value, 0..31           2 cyc
    fsr++;                  //                                        1 cyc
    dc3 = indf;             // row 3 (gp4) pwm value, 0..31           2 cyc
    addr = fsr + 1;         // save array address                     2 cyc
  }
Gentlemen, thank you both.

Mike
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…