CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Question about built_in function input_state(SOLVED)

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
naughty_mark



Joined: 29 Aug 2012
Posts: 97

View user's profile Send private message

Question about built_in function input_state(SOLVED)
PostPosted: Wed Jul 02, 2014 7:28 pm     Reply with quote

Hi everyone,

I am using dsPIC33EP512MU814 with CCS compiler v5.016

What I am trying to do is to read the states of pins and then process. For easy coding, I put the pins I want to read in a array like
Code:

static unsigned int16 buttonArray[BUTTON_INPUT_AMOUNT] = {PIN_A1,PIN_A2,PIN_A3,PIN_A4,PIN_A5};


and then I use FOR loop to read those pins one by one like:
Code:

   unsigned char checkInd;

   for(checkInd = 0; checkInd < BUTTON_INPUT_AMOUNT; checkInd++)
   {
      transDataBuf[checkInd] = input_state(buttonArray[checkInd]);
   }

But compiler gives error "Expression must evaluate to a constant".

It looks this function doesn't support in this way. I know I can manually code to read those inputs one by one, but beside that, anyone have a good idea to deal with this scenario?

Thanks for your help and time.

Kind Regards
Mark


Last edited by naughty_mark on Thu Jul 03, 2014 12:43 am; edited 4 times in total
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Wed Jul 02, 2014 8:27 pm     Reply with quote

compiler is telling you it expects a constant for input_state()'s
argument. it is only able to accept a "pin" argument as a CONST at compile time, not in runtime with VARS .

you have few pins so use SWITCH and do an input_state for each pin .....
will be like 8 lines of 'c code -with the benefit of it being way more
code space, and execution time- efficient than if you COULD get away with your code, using vars

just because you think your 'C for(,,) loop is elegant and compact,
if you tried to generate input_state with VAR args, it will make a bloated mess of wasted clock cycles, and be horribly inefficient as a bonus
.. Very Happy Very Happy
naughty_mark



Joined: 29 Aug 2012
Posts: 97

View user's profile Send private message

PostPosted: Wed Jul 02, 2014 9:02 pm     Reply with quote

asmboy wrote:
compiler is telling you it expects a constant for input_state()'s
argument. it is only able to accept a "pin" argument as a CONST at compile time, not in runtime with VARS .

you have few pins so use SWITCH and do an input_state for each pin .....
will be like 8 lines of 'c code -with the benefit of it being way more
code space, and execution time- efficient than if you COULD get away with your code, using vars

just because you think your 'C for(,,) loop is elegant and compact,
if you tried to generate input_state with VAR args, it will make a bloated mess of wasted clock cycles, and be horribly inefficient as a bonus
.. Very Happy Very Happy


Thanks for your reply, asmboy.
I understand that I can use SWITCH to solve this problem, and I noticed that function needs "constant" not VAR. The reason that I asked this question is I am doing bootloader with some I/O test feature, and I want that code can be cross-projects plant easily, which means in future I don't need to touch the code, just modify the Variable arrays, that is my real purpose.
I think someone may had that experience before and may have a better solution rather than SWITCH.
Thanks for your help, and if anyone have a better idea, I do appreciate.

Kind Regards
Mark

EDIT: what I can think is because in device header file, there is offset value of pin in memory location, such as
Code:

#define PIN_A1   22868

I wonder if there is any command or ASM instruction to let me use this offset to read the pin state? If yes, what the command is? and that "22868" is the offset of what?
naughty_mark



Joined: 29 Aug 2012
Posts: 97

View user's profile Send private message

PostPosted: Wed Jul 02, 2014 9:35 pm     Reply with quote

Hi guys,

I searched that thread, and the last second poster by ckielstra is useful, but I am still not sure if it works for dsPIC33EP512MU814.

http://www.ccsinfo.com/forum/viewtopic.php?t=46396

If it works, my question will be what should I use with ccs pin definition, I mean for example if PIN_A1 is 22826, what that mean? I can not find relative register information in its document.

Thanks for help
naughty_mark



Joined: 29 Aug 2012
Posts: 97

View user's profile Send private message

PostPosted: Wed Jul 02, 2014 10:51 pm     Reply with quote

Hi guys,

I just tried the method in that thread provided by "ckielstra", it works.
Shift that number right to 3 bits means divided by 8, which will give us the port address, just a little bit different for dsPIC33EP512MU814, it is the bit mask judge, because this micro has 16 pins in a port, so the code will be

Code:

char input_pin_state(int16 ccs_pin)
{
    int16 io_port;
    char bitmask;
    char retval;

    io_port = ccs_pin >> 3;                  // Get the i/o port address
    bitmask = 1 << (ccs_pin & 15);            // get mask
    retval = (*io_port & bitmask) ? 1 : 0;   // Read pin (ret. 0 or 1)

    return retval;
}


Regards
Mark

EDIT: I found a problem that if the pin number is from 0 to 7, that code is ok, if pin above 7 such as PIN_K13, the reading is always 0. I tried many different ways, and use the code as following but still not work, anyone know what's wrong?
Code:

char input_pin_state(int16 ccs_pin)
{
    int16 io_port;
    char bitmask;
    char shiftStep,pinNum,retval;

    io_port = ccs_pin >> 3;                  // Get the i/o port address
    pinNum = ccs_pin & 15;
    if(pinNum < 8)
    {
        shiftStep = (ccs_pin & 15);
    }
    else
    {
        shiftStep = (ccs_pin & 15) - 8;
    }
    bitmask = 1 << shiftStep;            // get mask
    retval = ((*(io_port+pinNum/8)) & bitmask)? 1 : 0;   // Read pin (ret. 0 or 1)

    return retval;
}


Last edited by naughty_mark on Thu Jul 03, 2014 12:41 am; edited 2 times in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Thu Jul 03, 2014 12:22 am     Reply with quote

_char_ bitmask......
naughty_mark



Joined: 29 Aug 2012
Posts: 97

View user's profile Send private message

PostPosted: Thu Jul 03, 2014 12:36 am     Reply with quote

Ttelmah wrote:
_char_ bitmask......


Thanks Ttelmah,
I just got it works, my previous code has a bug in it. Just re-put it on.

Code:

char input_pin_state(int16 ccs_pin)
{
    int16 io_port;
    char bitmask;
    char shiftStep,pinNum,retval;

    io_port = ccs_pin >> 3;                  // Get the i/o port address
    pinNum = ccs_pin & 15;
    if(pinNum < 8)
    {
        shiftStep = (ccs_pin & 15);
    }
    else
    {
        shiftStep = (ccs_pin & 15) - 8;
    }
    bitmask = 1 << shiftStep;            // get mask
    retval = ((*io_port) & bitmask)? 1 : 0;   // Read pin (ret. 0 or 1)

    return retval;
}


And it works fine.
Thanks for you guys support. I do appreciate.

Mark
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Thu Jul 03, 2014 12:47 am     Reply with quote

As a comment, you do realise that CCS has a function that does all the masking for your?.

Code:


char input_pin_state(int16 ccs_pin)
{
    int16 * io_port; //ensures bit_test treats the return as 16bit
    io_port = ccs_pin >> 3;                  // Get the i/o port address
    return (bit_test((*io_port),(ccs_pin & 15));
}
naughty_mark



Joined: 29 Aug 2012
Posts: 97

View user's profile Send private message

PostPosted: Thu Jul 03, 2014 1:04 am     Reply with quote

Whoops~~So that means I don't need to take care of the pin number and its masking, that is very good, I will use that. Thanks for your help, Ttelmah. Very Happy

EDIT: I just doubt if that bit_test gonna work, because (*io_port) will be a BYTE data, and if pin number is higher than 7 which means (ccs_pin &15) is greater than 7, I doubt that function can find a proper value on a BYTE data with higher bit number. Anyway, I may try it tmr.
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Thu Jul 03, 2014 1:13 am     Reply with quote

No.

That's why I made it a _pointer_ to an 'int16'.

The compiler then knows it is dealing with an int16 value. Smile
naughty_mark



Joined: 29 Aug 2012
Posts: 97

View user's profile Send private message

PostPosted: Thu Jul 03, 2014 4:32 pm     Reply with quote

Ttelmah wrote:
No.

That's why I made it a _pointer_ to an 'int16'.

The compiler then knows it is dealing with an int16 value. Smile


Yes, Ttelmah. You are right. If you use pointer to int16, then that should be fine.
But yesterday, when I tried to solve why the upper byte input reading not correct, and found the bit shift is not right because with my code, the *io_port is a byte value, notice in the code I use "int16 io_port", I just followed the code in the thread, and I thought that is wrong and change to "int16 *io_port", the result is I can compile but when the code implemented there, it will reset the micro, and I guess because ccs_pin is the address in the ROM, and maybe I can not access ROM value by using a pointer which is ok to access var in RAM. that is why I use my current code which posted above.
Maybe I am wrong, but the fact is when I use "int16 *io_port", I got reset.
Thanks for your time.

Mark
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Fri Jul 04, 2014 12:33 am     Reply with quote

It needs one change....

Code:

char input_pin_state(int16 ccs_pin)
{
    int16 * io_port; //ensures bit_test treats the return as 16bit
    io_port = (ccs_pin >> 3) & 0xFFFE;    // Get the i/o port address
    return (bit_test((*io_port),(ccs_pin & 15));
}


Note the mask.

The chip errors because as originally posted it was trying to access an odd address, when values are above 7. It can't do a 16bit fetch from an odd address.

You could use the internal function, and 8bit fetches, with:
Code:

char input_pin_state(int16 ccs_pin)
{
    int8 * io_port; //8bit return data
    io_port = (ccs_pin >> 3);    // Get the i/o port address
    return (bit_test((*io_port),(ccs_pin & 7));
}


Best Wishes
naughty_mark



Joined: 29 Aug 2012
Posts: 97

View user's profile Send private message

PostPosted: Sun Jul 06, 2014 5:20 pm     Reply with quote

Thanks Ttelmah. That makes sense. I do appreciate for your help~ Smile
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Mon Jul 07, 2014 12:26 am     Reply with quote

It's worth just adding one comment.

You were using:

int16 io_port;

and accessing with:

retval = ((*io_port) & bitmask)? 1 : 0;

This is potentially slightly dangerous.

It _relies_ on the assumption that the compiler will treat 'io_port' as a pointer to an int8.

Problem is that this is not guaranteed, so it only takes CCS to change this assumption on a future compiler version, and it'll stop working, or crash.

Better either to declare io_port as "int8 * io_port", or explicitly cast it when you use it. So:

retval = ((*(int8 *)io_port) & bitmask)? 1 : 0;

These are the nasty little 'waiting to catch you' problems, that being explicit with types, helps to reduce. C is not explicitly typed, so 'allows' you to use an int16 as a pointer, without casting. On many languages this would not be accepted without an explicit cast (or the equivalent in that language), but while C's flexibility here is useful, it also brings with it dangers/responsibility....

Best Wishes
naughty_mark



Joined: 29 Aug 2012
Posts: 97

View user's profile Send private message

PostPosted: Tue Jul 08, 2014 1:03 am     Reply with quote

Very valuable point, Ttelmah. I will be wary of that and do explicit cast just in case like you said.
I do appreciate your great help and I learnt a lot.

Kind Regards
Mark
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group