  | 
	  | 
		 
	 
	
		| View previous topic :: View next topic   | 
	 
	
	
		| Author | 
		Message | 
	 
	
		
			doguhanpala
 
 
  Joined: 05 Oct 2016 Posts: 120
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				| ports with parameters | 
			 
			
				 Posted: Mon Feb 12, 2018 3:53 pm     | 
				     | 
			 
			
				
  | 
			 
			
				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: 21708
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Mon Feb 12, 2018 5:36 pm     | 
				     | 
			 
			
				
  | 
			 
			
				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:
 
 
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: 9589 Location: Greensville,Ontario 
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Mon Feb 12, 2018 5:59 pm     | 
				     | 
			 
			
				
  | 
			 
			
				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: 120
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Tue Feb 13, 2018 12:42 am     | 
				     | 
			 
			
				
  | 
			 
			
				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: 19967
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Tue Feb 13, 2018 1:33 am     | 
				     | 
			 
			
				
  | 
			 
			
				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: 120
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Tue Feb 13, 2018 2:05 am     | 
				     | 
			 
			
				
  | 
			 
			
				 	  | 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: 120
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Tue Feb 13, 2018 2:40 am     | 
				     | 
			 
			
				
  | 
			 
			
				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: 19967
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Tue Feb 13, 2018 5:07 am     | 
				     | 
			 
			
				
  | 
			 
			
				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: 1401
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Thu Feb 15, 2018 1:21 pm     | 
				     | 
			 
			
				
  | 
			 
			
				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: 21708
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Thu Feb 15, 2018 1:30 pm     | 
				     | 
			 
			
				
  | 
			 
			
				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: 120
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Fri Feb 16, 2018 1:51 am     | 
				     | 
			 
			
				
  | 
			 
			
				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: 19967
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Fri Feb 16, 2018 3:10 am     | 
				     | 
			 
			
				
  | 
			 
			
				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
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Fri Feb 16, 2018 5:09 am     | 
				     | 
			 
			
				
  | 
			 
			
				 	  | 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: 1401
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Fri Feb 16, 2018 9:23 am     | 
				     | 
			 
			
				
  | 
			 
			
				 	  | 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). | 
			 
		  | 
	 
	
		  | 
	 
	
		 | 
	 
 
  
	 
	    
	   | 
	
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
  
		 |