Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Simple C problem? Am I blind?

Status
Not open for further replies.

dslocum

Newbie level 5
Newbie level 5
Joined
Feb 5, 2016
Messages
10
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
90
I'm using MikroC Pro for PIC24. Reasonably comfortable in C, but this has been difficult problem for many hours.

My hardware uses an electronic attenuator chip that works just fine. I can program it to 'attenuate' for 0 (full volume) to 127 (minimum volume / mute). That works great. Simple stripped down code below, raises and lowers the volume thru the full range of the chip (works). I left off obvious declarations, etc for clarity.

Code:
void Vol_Output(unsigned short channel, unsigned short valueVOL) {
  unsigned short temp;
  
  // Send address Byte
  Vol_Write_Byte(channel);

  // Send volume value Byte
  Vol_Write_Byte(valueVOL);
  
}

void main(void) {
  unsigned short i; 

    // init stuff here...

  while(1) {
    for(i=0; i<127; i++) {    //
      Vol_Output(0, i);    
      Delay_ms(10);
    }
    
    for(i=127; i>0; i--) {
      Vol_Output(0, i);
       Delay_ms(10);
    }
  }
}

Instead of attenuation, I want to have the volume increase from minimum at 0, to maximum at 127. I should be able to simply do the following to subtract 'i' from 127, right? It doesn't work.

I've tried unsigned, signed, shorts, chars, ints, variables of 127 in place of literals. No joy here today.

Watching variables while single stepping in the debugger seems OK. What am I not seeing?

Code:
void Vol_Output(unsigned short channel, unsigned short valueVOL) {
  unsigned short temp;
  
  // Send address Byte
  Vol_Write_Byte(channel);

  // added this to 'invert' the input volume
  temp = 127 - valueVOL;

  // Send volume value Byte
  Vol_Write_Byte(temp);
  
}

void main(void) {
  unsigned short i; 

    // init stuff here...

  while(1) {
    for(i=0; i<127; i++) {    //
      Vol_Output(0, i);    
      Delay_ms(10);
    }
    
    for(i=127; i>0; i--) {
      Vol_Output(0, i);
       Delay_ms(10);
    }
  }
}
 

"Doesn't work" means you are seeing what exactly?
 

Just reverse the two for loops but can you make out the difference? What you are trying to do?
 

"Doesn't work" means you are seeing what exactly?

Good point.

The "Vol_Write_Byte" routine serializes the byte via 'bit-banged' SPI, which works fine if I don't try what I'm trying to do.

If I run it in the software debugger, everything looks fine with results as expected in both test cases. Since I can't (or don't know how to) hardware debug this thing, it's actually hard to know how to answer you, other than there is ever nothing output from the attenuator chip's audio output.

Just in case I got numbers that I wasn't expecting, I even tried keeping keeping the 'temp' variable in range by doing this:

Code:
  if(temp > 127)
      temp=127;
  if(temp < 0)
      temp = 0;

That way, I'm pretty sure I'm sending numbers that aren't whacky.

So again, I'm just getting no audio output, which would indicate that I'm sending the chip a value of > 127 (anything > 127 is MUTE - no output)

- - - Updated - - -

Just reverse the two for loops but can you make out the difference? What you are trying to do?

Thanks, I understand your suggestion but that's not the point of what I'm trying to do. I'm trying to change the input to the chip from 0=full volume;127=no volume, TO 127=full volume;0=no volume.
 

I would recommend you make a test, replacing the sequence...

Code:
  // added this to 'invert' the input volume
  temp = 127 - valueVOL;

  // Send volume value Byte
  Vol_Write_Byte(temp);

by just...

Code:
Vol_Write_Byte(127 - valueVOL)

I fear that some unwanted type casting are being performed, cutting out part of the value.
 
Code is correct. You get (as you already wrote) correct values during stepping, so the error is not in the code.

Are you sure the delays provide enough time for hardware to adjust?
Are you sure there is no need to add any termination byte?
Is the Vol_Output function working propertly?
 
"unwanted type casting"? Only if the compiler ignores elementary C rules. I've seen strange compiler bugs, in so far I won't deny the possibility.

I would either inspect the assembly listing or trace code operation with a hardware debugger to see what happens.
 

"unwanted type casting"? Only if the compiler ignores elementary C rules. I've seen strange compiler bugs, in so far I won't deny the possibility.

I would either inspect the assembly listing or trace code operation with a hardware debugger to see what happens.

I thought long and hard about possible weird casting issues and have tried several things, to no avail.

I wish I knew how to hardware debug this. It's a custom design (mine), but I only have a PICKIT3 with ICSD for programming. I've tried to set the project to output debugger info, but can't seem to get it to work. Not even sure how. :-(

I'm generally comfortable with assembly language (years ago), but I don't know PIC assembly. I could have a go at getting a dump if you think it might help.
 

Re: Simple C problem? Am I blind?

Code is correct. You get (as you already wrote) correct values during stepping, so the error is not in the code.

Are you sure the delays provide enough time for hardware to adjust?
Are you sure there is no need to add any termination byte?
Is the Vol_Output function working propertly?

Thanks for the suggestions. I'll make some tests tomorrow and get back.

Good thought, but I'm not sure we can assume the compiled code is correct because the SW debug emulator says it is when we single step thru it. I will have to imagine them as two separate entities until proven differently.
 

If the shown code is complete, you are sending alternatively channel and volume information, without any framing. I won't expect this to work in a first order.

But may be you have stripped off essential things. In any case, writing data to the hardware is the place where debugging could start. Are you writing at all? Writing the right data? What do you see on the wire level?
 

There are a few simple debugging techniques to use, so you will be sure that no casting errors occur.
One of them is to use a snippet of code in your function:
Code:
void Vol_Output(unsigned short channel, unsigned short valueVOL) {
  unsigned short temp;
  
  // Send address Byte
  Vol_Write_Byte(channel);

  // added this to 'invert' the input volume
  temp = 127 - valueVOL;

  if(temp > 127)
         set a led1 ON //this led should never be lit
  if((temp < 64){//the led2 should toggle and could be watched for pulses or the mcu pin
                      //could be measured with a DVM
         set led2 ON
  } else {
         set led2 OFF
  }


         
  // Send volume value Byte
  Vol_Write_Byte(temp);
  
}
 
There are a few simple debugging techniques to use, so you will be sure that no casting errors occur.
One of them is to use a snippet of code in your function:
Code:
void Vol_Output(unsigned short channel, unsigned short valueVOL) {
  unsigned short temp;
  
  // Send address Byte
  Vol_Write_Byte(channel);

  // added this to 'invert' the input volume
  temp = 127 - valueVOL;

  if(temp > 127)
         set a led1 ON //this led should never be lit
  if((temp < 64){//the led2 should toggle and could be watched for pulses or the mcu pin
                      //could be measured with a DVM
         set led2 ON
  } else {
         set led2 OFF
  }


         
  // Send volume value Byte
  Vol_Write_Byte(temp);
  
}

Good suggestion.

I this works fine as expected when I don't try my inverting trick (127 - valueVOL), turning on the LED 1/2 way thru the ramp cycles. LATB0_bit is the LED.
Code:
// WORKS
  temp = valueVOL;

  if(temp > 64) {
      LATB0_bit = 1;
  }
  else  {
      LATB0_bit = 0;
  }

This does NOT light the LED, as expected when I don't try my inverting trick, so I know there's no value > 127.
Code:
// WORKS
  temp = valueVOL;

  if(temp > 127) {
      LATB0_bit = 1;
  }
  else  {
      LATB0_bit = 0;
  }

NOW, when I try my inverting code....

Code:
// NOT WORKING, LED DOES NOT LIGHT (no value over 127

  temp = 127 - valueVOL;

  if(temp > 127) {
      LATB0_bit = 1;
  }
  else  {
      LATB0_bit = 0;
  }

So what is the value????? This says the value is stuck at 127. !!!!

Code:
// NOT WORKING, LED LIGHTS CONSTANTLY

  temp = 127 - valueVOL;

  if(temp > 126) {
      LATB0_bit = 1;
  }
  else  {
      LATB0_bit = 0;
  }

Further proof something is wrong...

Code:
// NOT WORKING, LED LIGHTS CONSTANTLY

  temp = 127 - valueVOL;

  if(temp == 127) {
      LATB0_bit = 1;
  }
  else  {
      LATB0_bit = 0;
  }
 

You need to post the full configuration.
There isn't enough information to offer much help without it.

Mikro C is used by thousands of people - that isn't your issue.
Also your hardware & design should be checked to be sure
Debugging tip:
When something doesn't do what you know it should - the problem is "the knowing" almost every time.
We've all torn our hair out like this more than once I'll bet.

I'm guessing you've already sent 0 and got the correct output - then sent 127 right after
and then 0 again right after that and everything went fine?
Does your chip need a long settling time maybe?
Maybe your attenuator needs to be configured to enable reverse operation - a flag or
stepping from a specific value or something? Chips can be wierd sometimes.
(What chip is it - have you checked its data sheet?) How are you communicating
with it - via port B ? How is handshaking done?

lotsa questions here....
 
In MPLAB with Microchip compiler there is no problem, but you use the non C stadard, MicroC compiler. I also give it a try in simulation in MicroC and it still works fine.
Let's ignore correct C view and try something dummy.

Try this:
Code:
void Vol_Output(unsigned short channel, unsigned short valueVOL) {
  int temp;
  
  // Send address Byte
  Vol_Write_Byte(channel);

  // added this to 'invert' the input volume
  temp = 127 - ((int)valueVOL);

  // Send volume value Byte
  Vol_Write_Byte((unsigned short)temp);
  
}

and this:

Code:
void Vol_Output(unsigned short channel, unsigned short valueVOL) {
  unsigned short  temp;
  
  // Send address Byte
  Vol_Write_Byte(channel);

  // added this to 'invert' the input volume
  temp = ((unsigned short)127) - valueVOL;

  // Send volume value Byte
  Vol_Write_Byte(temp);
  
}
 
I had tried some casting early on, but tried your suggestions just now. Both fail. I also tried using 0b01111111 instead of 127.

I also tried setting a unsigned short = 127 and subtracting from the variable.

- - - Updated - - -

Moved it out of the function. This works fine BOTH ways. Flashes the LED about 50% dut

Code:
void main() {
  unsigned short z;
  unsigned short x;

  ANSB0_bit = 0;  // led bit
  LATB0_bit = 0;
  TRISB0_bit = 0;

  while(1) {

    for(z=0; z<127; z++) {

      // this works
      x =  z;

      // this also works
      //  x = 127 - z;

      if(x > 64) {
          LATB0_bit = 1;
      }
      else  {
          LATB0_bit = 0;
      }
      Delay_ms(10);
    }
  }
}

Trying a different simple function... Works fine.

Code:
void foo(unsigned short valueVOL) {
  unsigned short x;
  
  x = valueVOL;
  if(x > 64) {
      LATB0_bit = 1;
  }
  else  {
      LATB0_bit = 0;
  }
}

void main() {
  unsigned short z;

  ANSB0_bit = 0;  // led bit
  LATB0_bit = 0;
  TRISB0_bit = 0;

  while(1) {

    for(z=0; z<127; z++) {
      foo(z);
      Delay_ms(10);
    }
  }

I'm now going to build another function that does exactly what my other one is supposed to do. Grrrrrrr
 

Have you correclty selected PIC in the project?
Are your functions declared correctly before called?

Is your version of MicroC for evaluation only? If yes and you try to use more than 2Kbytes of code, it produces bugs in the compiling difficault to trace without viewing the assemby generated.
 
  • Like
Reactions: FvM

    FvM

    Points: 2
    Helpful Answer Positive Rating
PROBLEM SOLVED !

I want to thank everyone who helped me. You guys are great !!!:grin:

As with many things, it was a dumb oversight on my part.

I'm not going to think about how I was able to get what seemed to be bad data. I hope I don't loose too much sleep over it.

The problem was that I had several on these attenuator chips, each one controlling a different frequency bandpass filter. BUT, there was one 'master' attenuator chip that fed them all. By accident, I was turning that one off in my function and did not realize it, so there would be no output.

So, "127 - valueVOL" actually works.

Someone please kick me.!:bang:

Thanks so much again!
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top