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 support@ccsinfo.com

ports with parameters

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



Joined: 05 Oct 2016
Posts: 95

View user's profile Send private message

ports with parameters
PostPosted: Mon Feb 12, 2018 3:53 pm     Reply with quote

Hello everyone

I am trying to use the pins with a parameter. For example on 18f4550 pin_B2 is 31754. I am trying to add this value 1 and use the pin b3 which is 31755

i use this function and it works
Code:

output_high(DIGITAL_PORT_BASE + 1);


but

when i use this the code doesnt work. and compiler gives no warning or ect.

Code:
int rgb_port = 1;
output_high(DIGITAL_PORT_BASE + rgb_port);


i tried to change the type of rgb_port to long and int16 and byte but neither of them worked. Can you see what is the problem here.

Here is my full code. when i change the lines in neobit function.

output_high(DIGITAL_PORT_BASE+ rgb_port);

it does not work

however when i use

output_high(DIGITAL_PORT_BASE+ 1);

it works just fine

Code:

#include <18F4550.h>
#DEVICE ADC=10
#fuses HSPLL,NOWDT,NOMCLR,PROTECT,NOLVP,NODEBUG,NOBROWNOUT,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#use rs232(baud=9600, UART1, ERRORS,stream = bt)
#define DIGITAL_PORT_BASE PIN_B2

#define LEDNUM 1 // 1 led var

void neobit(int);
void led_on();
void led_choose(int,int,int,int); // x tane ledden hangisini yakacagimizi seciyor ve o led icin R,G ve B renk degerini bekliyor
void get_color();


unsigned int8 red[LEDNUM] = {};  //kirmizi degerleri  (1. ledin kirmizisi, 2. ledin kirmizisi seklinde ilerliyor)
unsigned int8 green[LEDNUM] = {}; //yesil degerleri
unsigned int8 blue[LEDNUM] = {};  // mavi degerleri
int rgb_port = 1;
//RGB ledlerdin her biri 24 bit komut bekliyor. ilk 8 bit yesilin parlaklığı, 2. 8 bit kirmizi ve  3. 8 bit mavi icin.

void main()
{
   delay_ms(2000);
   while(true)
   get_color();         
}

void neobit(int bit) // rgbdeki entegre '1' icin 0.9us high bekliyor. '0' icin ise 0.35us high bekliyor. Bu fonksiyon aldigi bite gore high ve low veriyor.
{
   if(bit==1)
   {
      output_high(DIGITAL_PORT_BASE);
      delay_cycles(6);
      output_low(DIGITAL_PORT_BASE);
   }
   else
   {
      output_high(DIGITAL_PORT_BASE);
      delay_cycles(3);
      output_low(DIGITAL_PORT_BASE);
   }
}

void led_on() // gelen renk degerinin bitlerine bakarak duruma gore '1' veya '0' gonderiyor. Girdigimiz integer degerini rgbye gonderiyoruz.
{
   int i=0;
   int a=0;
   for(a=0;a<LEDNUM;a++)
   {
      for(i=8;i>0;i--)
      {
         neobit(bit_test(green[a],(i-1)));
      }
      for(i=8;i>0;i--)
      {
         neobit(bit_test(red[a],(i-1)));
      }
      for(i=8;i>0;i--)
      {
         neobit(bit_test(blue[a],(i-1)));
      }
   output_low(DIGITAL_PORT_BASE);
   }
}


void get_color() // her bir led icin kullanicidan renk aliyor
{
int i=0;

         for(i=0;i<LEDNUM;i++)
         {
            red[i]=10;
            putc('r',bt);
            green[i]=0;
            putc('g',bt);
            blue[i]=50;
            putc('b',bt);
         }
led_on();
}
     
PCM programmer



Joined: 06 Sep 2003
Posts: 20419

View user's profile Send private message

PostPosted: Mon Feb 12, 2018 5:36 pm     Reply with quote

It worked for me. I made the test program shown below. Then I ran
it in MPLAB vs. 8.92 simulator with a Watch window open, showing LATB.
The Watch window shows:
Quote:
LATB F8A 0x08

The value of 0x08 shows that Pin B3 is set. This is the correct result.
This was tested with with CCS vs. 5.076.
Code:

#include <18F46K22.h>
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT
#use delay(clock=4M)

#define DIGITAL_PORT_BASE PIN_B2

//======================================
void main(void)
{
int16 rgb_port = 1;

output_high(DIGITAL_PORT_BASE + rgb_port);
 
while(TRUE);
}                                     
temtronic



Joined: 01 Jul 2010
Posts: 6319
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Feb 12, 2018 5:59 pm     Reply with quote

hopefully someone else will explain but I did a quick code test.
...stuff added to my program
#define test pin_b2
int8 offest=1;
...results from listing

Code:

190:               output_high(test);
  06A2    9493     BCF 0xf93, 0x2, ACCESS
  06A4    848A     BSF 0xf8a, 0x2, ACCESS
191:               output_high(test+1);
  06A6    9693     BCF 0xf93, 0x3, ACCESS
  06A8    868A     BSF 0xf8a, 0x3, ACCESS
192:               output_high(test+offest);
  06AA    0E0A     MOVLW 0xa
  06AC    2439     ADDWF 0x39, W, ACCESS
  06AE    6E3A     MOVWF 0x3a, ACCESS
  06B0    0E7C     MOVLW 0x7c
  06B2    6E3B     MOVWF 0x3b, ACCESS
  06B4    B0D8     BTFSC 0xfd8, 0, ACCESS
  06B6    2A3B     INCF 0x3b, F, ACCESS
  06B8    C03A     MOVFF 0x3a, 0x3c
  06BC    0E01     MOVLW 0x1
  06BE    6E3D     MOVWF 0x3d, ACCESS
  06C0    0E0F     MOVLW 0xf
  06C2    6E3F     MOVWF 0x3f, ACCESS
  06C4    0E89     MOVLW 0x89
  06C6    6E3E     MOVWF 0x3e, ACCESS
  06C8    DF5F     RCALL 0x588
  06CA    C03A     MOVFF 0x3a, 0x3c
  06CE    6A3D     CLRF 0x3d, ACCESS
  06D0    0E0F     MOVLW 0xf
  06D2    6E3F     MOVWF 0x3f, ACCESS
  06D4    0E92     MOVLW 0x92
  06D6    6E3E     MOVWF 0x3e, ACCESS
  06D8    DF57     RCALL 0x588
AND


0588    503C     MOVF 0x3c, W, ACCESS
  058A    0B07     ANDLW 0x7
  058C    6E00     MOVWF 0, ACCESS
  058E    303C     RRCF 0x3c, W, ACCESS
  0590    6E01     MOVWF 0x1, ACCESS
  0592    3201     RRCF 0x1, F, ACCESS
  0594    3201     RRCF 0x1, F, ACCESS
  0596    0E1F     MOVLW 0x1f
  0598    1601     ANDWF 0x1, F, ACCESS
  059A    5001     MOVF 0x1, W, ACCESS
  059C    243E     ADDWF 0x3e, W, ACCESS
  059E    6EE9     MOVWF 0xfe9, ACCESS
  05A0    0E00     MOVLW 0
  05A2    203F     ADDWFC 0x3f, W, ACCESS
  05A4    6EEA     MOVWF 0xfea, ACCESS
  05A6    6A01     CLRF 0x1, ACCESS
  05A8    2A01     INCF 0x1, F, ACCESS
  05AA    2A00     INCF 0, F, ACCESS
  05AC    D001     BRA 0x5b0
  05AE    3601     RLCF 0x1, F, ACCESS
  05B0    2E00     DECFSZ 0, F, ACCESS
  05B2    D7FD     BRA 0x5ae
  05B4    523D     MOVF 0x3d, F, ACCESS
  05B6    E003     BZ 0x5be
  05B8    5001     MOVF 0x1, W, ACCESS
  05BA    12EF     IORWF 0xfef, F, ACCESS
  05BC    D003     BRA 0x5c4
  05BE    1E01     COMF 0x1, F, ACCESS
  05C0    5001     MOVF 0x1, W, ACCESS
  05C2    16EF     ANDWF 0xfef, F, ACCESS
  05C4    0C00     RETLW 0




As you can see in the code at 190 and 191 , the compiler creates very,very 'tight' or short code.
In 192 the compier creats 20+ lines AND there are 2 'calls' so a routine at 0x0588, which itself is some 20 + instructions.
All told the 3rd version is at least 60 times bigger and therefore 60 times slower in execution !
As stated in the other reply, this is why it doesn't run. Actually it does run,just won't work as expected. Your neopxl is 'time sensitive', same as the 1 wire devices. Just copy the 'driver',recode for more pins.

Jay


Last edited by temtronic on Tue Feb 13, 2018 6:41 am; edited 2 times in total
doguhanpala



Joined: 05 Oct 2016
Posts: 95

View user's profile Send private message

PostPosted: Tue Feb 13, 2018 12:42 am     Reply with quote

i am sorry, i forgot to explain how iy doesnt work. i cannot see a color on rgb. if i use output_high(digital_port_base + 1) i see the color. the rgb led is ws2812 5050.

pcm programmer, i wrote a new function and did what you did. it worked for me too. i cannot make the neobit function work. it seems the problem is in there. however, using 1 instead of rgb_port makes it work too. i could not find the mistake.
Ttelmah



Joined: 11 Mar 2010
Posts: 13748

View user's profile Send private message

PostPosted: Tue Feb 13, 2018 1:33 am     Reply with quote

OK.

Key is to understand what is involved.

If you code a 'fixed' pin (so input(PIN_A1) for example), the maths is all done at compile time. The code that results is just the actual machine instructions to access this pin. Hence small/fast code.
Using a variable for a pin, brings a big cost. At run time, the code has to work out the port address and the bit masks needed to access the pin. Typically perhaps a dozen instructions. Now this won't work with anything involving tight timings. This has been covered here before for the Dallas 'one wire' bus.
If you search for multiple 18B20, you should find threads about this. The reliable solution, is to just have duplicate code I'm afraid....
So the code is actually 'working', but the overhead involved makes it not function for the timings needed. This is unfortunately inherent with the chip, not something that can be fixed by ingenious code.
It is possible to solve for multiple bits on the same port, by doing the maths yourself, in advance of the timing operations. Whether this might work for your would depend on how many pins you actually want to use, and where they are on the chip?. Generally if the number of pins involved is small, it is actually easier to just use the duplicate code solution.
doguhanpala



Joined: 05 Oct 2016
Posts: 95

View user's profile Send private message

PostPosted: Tue Feb 13, 2018 2:05 am     Reply with quote

Ttelmah wrote:
OK.

Key is to understand what is involved.

If you code a 'fixed' pin (so input(PIN_A1) for example), the maths is all done at compile time. The code that results is just the actual machine instructions to access this pin. Hence small/fast code.
Using a variable for a pin, brings a big cost. At run time, the code has to work out the port address and the bit masks needed to access the pin. Typically perhaps a dozen instructions. Now this won't work with anything involving tight timings. This has been covered here before for the Dallas 'one wire' bus.
If you search for multiple 18B20, you should find threads about this. The reliable solution, is to just have duplicate code I'm afraid....
So the code is actually 'working', but the overhead involved makes it not function for the timings needed. This is unfortunately inherent with the chip, not something that can be fixed by ingenious code.
It is possible to solve for multiple bits on the same port, by doing the maths yourself, in advance of the timing operations. Whether this might work for your would depend on how many pins you actually want to use, and where they are on the chip?. Generally if the number of pins involved is small, it is actually easier to just use the duplicate code solution.


thank you for your answer Ttelmah. i will try what you said.

i want to use one pin. the project requires it.

i thought that the problem might be about speed actually. i tried to make the adding rgb port on a different place.

the code was like this

int16 port= digital_port_base + rgb_port;
output_high(port);

it did not work. i thought the adding process takes too long so if i do it 1 time it would solve my problem. you said the problem is the integer being there which explains why this code did not work too. i will try to write a switch case function. if rgb port is 0 digitalportbase is 31754 if 2, 31755. hope it works. thank you so much!
doguhanpala



Joined: 05 Oct 2016
Posts: 95

View user's profile Send private message

PostPosted: Tue Feb 13, 2018 2:40 am     Reply with quote

as you said ttelmah, this ugly piece of code worked for me


Code:
void neobit(int bit,int port) // rgbdeki entegre '1' icin 0.9us high bekliyor. '0' icin ise 0.35us high bekliyor. Bu fonksiyon aldigi bite gore high ve low veriyor.
{
switch(port){

   case 0:
      if(bit==1)
      {
         output_high(31754);
         delay_cycles(6);
         output_low(31754);
      }
      else
      {
         output_high(31754);
         delay_cycles(3);
         output_low(31754);
      }
      break;
    case 1:   
    if(bit==1)
      {
         output_high(31755);
         delay_cycles(6);
         output_low(31755);
      }
      else
      {
         output_high(31755);
         delay_cycles(3);
         output_low(31755);
      }
      break;
      case 2:   
    if(bit==1)
      {
         output_high(31756);
         delay_cycles(6);
         output_low(31756);
      }
      else
      {
         output_high(31756);
         delay_cycles(3);
         output_low(31756);
      }
      break;
}
}
Ttelmah



Joined: 11 Mar 2010
Posts: 13748

View user's profile Send private message

PostPosted: Tue Feb 13, 2018 5:07 am     Reply with quote

As a comment though, if you are only actually using one pin, then just use a #define, rather than a variable.
Code:

#define NEOPIN PIN_xx //set this to the pin you want

void neobit() // rgbdeki entegre '1' icin 0.9us high bekliyor. '0' icin ise 0.35us high bekliyor. Bu fonksiyon aldigi bite gore high ve low veriyor.
{
    output_high(NEOPIN);
    delay_cycles(6);
    output_low(NEOPIN);
}


You can then compile for any pin you want, by just changing the define.
jeremiah



Joined: 20 Jul 2010
Posts: 997

View user's profile Send private message

PostPosted: Thu Feb 15, 2018 1:21 pm     Reply with quote

As an additional idea, if you do end up using multiple pins (as your example code shows), then you can use a macro to tidy up the code some:

Code:

#define neobit_impl(bit,pin)     \
   if (bit == 1){                \
      output_high(pin);          \
      delay_cycles(6);           \
      output_low(pin);           \
   }else{                        \
      output_high(pin);          \
      delay_cycles(3);           \
      output_low(pin);           \
   }   
   

void neobit(int bit,int port)
{
   switch(port){
      default:
      case 0: neobit_impl(bit,31754);  break;
      case 1: neobit_impl(bit,31755);  break;
      case 2: neobit_impl(bit,31756);  break;
     
   }
}


It will generate identical code to your example (well I added the "default" case in the switch statement, but otherwise identical), so it will still take up the same code space and will run just as fast, but it might be easier for you to read.
PCM programmer



Joined: 06 Sep 2003
Posts: 20419

View user's profile Send private message

PostPosted: Thu Feb 15, 2018 1:30 pm     Reply with quote

Also, the o.p. is using magic numbers which actually come from the .h
file of the PIC:
Code:

#define PIN_B2  31754
#define PIN_B3  31755
#define PIN_B4  31756

There is little reason to use magic numbers, so an improvement would be:
Code:

switch(port){
      default:
      case 0: neobit_impl(bit, PIN_B2);  break;
      case 1: neobit_impl(bit, PIN_B3);  break;
      case 2: neobit_impl(bit, PIN_B4);  break;
doguhanpala



Joined: 05 Oct 2016
Posts: 95

View user's profile Send private message

PostPosted: Fri Feb 16, 2018 1:51 am     Reply with quote

Thank you for yor answers.

jeremiah, on your code

Code:
#define neobit_impl(bit,pin)   


is pin an integer? using an integer on the neobit function slows my code and rgb doesnt show a color. if its not, can you tell me what it is?
Ttelmah



Joined: 11 Mar 2010
Posts: 13748

View user's profile Send private message

PostPosted: Fri Feb 16, 2018 3:10 am     Reply with quote

As a general solution, let me post a relatively efficient way of doing multiple pins:
Code:

#define SELECTED_HIGH() *Physical_port |= mask
#define SELECTED_LOW() *Physical_port &= not_mask

unsigned int16 Physical_port;
unsigned int8 mask, not_mask;

void select(unsigned int16 pin)
{
    Physical_port=pin/8;
    mask=0;
    bit_set(mask, pin & 7);
    not_mask=mask^0xFF;
}

#inline
void neobit(void) //Pulse the currently selected pin
{
    SELECTED_HIGH(); //set selected pin high
    delay_cycles(6);
    SELECTED_LOW(); //set selected pin low
}

//Then call this like:
    select(PIN_A1); //whatever pin you are currently using
    neobit(); //pulse the selected pin


What you do is 'select' the pin you want, and then the OR and the & function like the output high and output low.
One 'caveat', the pin has to have been switched to drive in advance (this doesn't change the TRIS), but assuming the setup code will already have used an output_high or an output low to preset the pin, it'll already have the TRIS set correctly. This is almost as fast as the 'non variable' version. This is what I was referring to earlier when I talked about 'doing the maths in advance'. The 'select' function, does the maths to generate the bit masks and the physical port address.

So you can have the complete function set required to do whatever operation(s) you require, and just 'select' the pin(s) required, and call these.
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Fri Feb 16, 2018 5:09 am     Reply with quote

doguhanpala wrote:

jeremiah, on your code

Code:
#define neobit_impl(bit,pin)


is pin an integer? using an integer on the neobit function slows my code and rgb doesnt show a color. if its not, can you tell me what it is?


#define is a text substitution, it doesn't "know" about types, it simply replaces "pin" with the text you give it. It is not a function in the C sense at all; there is no call and return; only text replacement. It therefore produces inline code. Pin is not a "number" at all, merely text.

Pin constants are unsigned int16s. Int is unsigned 8 bit on 12/16/18 PICs, and signed int16 on 24/dsPic/33s.
jeremiah



Joined: 20 Jul 2010
Posts: 997

View user's profile Send private message

PostPosted: Fri Feb 16, 2018 9:23 am     Reply with quote

doguhanpala wrote:
Thank you for yor answers.

jeremiah, on your code

Code:
#define neobit_impl(bit,pin)   


is pin an integer? using an integer on the neobit function slows my code and rgb doesnt show a color. if its not, can you tell me what it is?


As RF_Developer said, it isn't a function so there is no type. The type of "pin" is whatever you put there. If you put a constant number, it will be a constant number. If you put an integer variable, it will be an integer variable. The code I posted will expand to *exactly* the same code you posted. It is text substitution (as RF_Developer mentioned to you)

I would highly recommend you reading up on how C macros work. They can be very powerful (and also dangerous).
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